mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
47880: Create branch for Cloud Convergence from the latest state of HEAD (Revision 47874) 47886: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 33052: (RECORD ONLY) Branch for Enterprise 4.0 service pack development 38002: (RECORD ONLY) Create branch for 4.1 Enterprise releases, based on 4.0.2 38003: (RECORD ONLY) Update version to 4.1.0 38079: (RECORD ONLY) Updated schema version to 5100 38536: (RECORD ONLY) Merged V4.1-BUG-FIX to V4.1 38219: ALF-14674: DOS voodoo to make start_deployment.bat work, as installed by Bitrock 38344: ALF-14674: Deployment installer still doesn't work - Use ${installdir.escape_backslashes} instead of ${installdir} 38471: ALF-14674: Deployment installer still doesn't work - Correction to use of ${installdir.escape_backslashes} 39519: (RECORD ONLY) Merged PATCHES/V4.0.2 to V4.1 38899: ALF-15005: Merged V4.0-BUG-FIX to PATCHES/V4.0.2 37920: ALF-13816: Permission Denied on web-client browsing if parent does not inherit permissions - FileFolderService getNamePath() now performs toFileInfo() as SystemUser. 38900: ALF-15005: Merged V4.1-BUG-FIX to PATCHES/V4.0.2 38549: ALF-11861: Maintain the same defuault root of WebDav for Alfresco 4.0 as was in pre-4.0 Removed overriding protocols.rootPath property from installer and enterprise overlay versions of alfresco-global.properties so that correct setting in repository.properties is used. 39494: ALF-15213 / ALF-15170: Can't change folder permissions in Private or Public-moderated sites - Fix by Dmitry V 44843: (RECORD ONLY) Created hotfix branch off V4.1 build 372 revision 44743 (candidate 4.1.2 release) 45708: (RECORD ONLY) Merged PATCHES/V4.1.2 to PATCHES/V4.1.3 45570: Merged V3.4-BUG-FIX to PATCHES/V4.1.2 43939: ALF-17197 / ALF-16917: Merged PATCHES/V3.4.11 to V3.4-BUG-FIX 43896: MNT-198: Activity feeds get not generated in private sites for added files if username in LDAP-AD contains uppercase letters - Now we can cope with a runAs where the username is in the wrong case 45714: (RECORD ONLY) Merged BRANCHES/DEV/V4.1-BUG-FIX to PATCHES/DEV/V4.1.3 45513: MNT-279: Use binary search in cached authority search to cut down search time when a group contains an astronomical number of authorities - Experimental fix to cut down on severe profiling hit 45715: (RECORD ONLY) Merged BRANCHES/DEV/V4.1-BUG-FIX to PATCHES/V4.1.3 44848: Fix for ALF-17178 SolrLuceneAnalyser.findAnalyser generating InavlidQNameExceptions wher they are easily protected. 46188: (RECORD ONLY) Merged BRANCHES/DEV/V4.1-BUG-FIX to PATCHES/V4.1.3 46014: Fix for ALF-17732 - SWF files are considered insecure content and should not be displayed directly in the browser. 46160: Fix for ALF-17759 - HTML files are stripped from metadata and style information after they are uploaded. 46165: Fix for ALF-17787 - Site Members 'All Members' link should not run query immediately 46169: Fix for ALF-17787 - Site Members 'All Members' link should not run query immediately - missing file 46186: Fix for ALF-17786 - Site dashboard page issues too many requests (Site Members dashlet issues avatar requests when it doesn't need too) 46242: (RECORD ONLY) Merged BRANCHES/DEV/V4.1-BUG-FIX to PATCHES/V4.1.3: 46184: Refactoring a test class to use JUnit Rules - as part of attempt to reproduce ALF-17797. 46192: Enhancement to JUnit Rule TemporaryNodes.java as required by fix for ALF-17797. 46194: Fix for ALF-17797. AddFailedThumbnailActionExecuter is failing. 46710: (RECORD ONLY) Create branch for Cloud Convergence from the latest state of 4.1.3 (RC5, Build 85, Revision 46648) 47908: Merged from DEV/CONV_V143 to DEV/CONV_HEAD 46788: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30323: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30171: ALF-9613: caching content store. Various improvements and bug fixes. Including: 30325: THOR-114: S3 content store 30326: THOR-128: S3 content store 30333: THOR-139 F101: Get account for user e-mail id 30335: Merge from THOR0 to THOR1 r30274: THOR-135 is email address accepted by Alfresco? Part One. 30340: THOR-99: Thor module - enable tests 30341: Removing duplicate account-service-context.xml file. 30343: Merge THOR0 to THOR1 30339: Test email singup in Share complete 30338: New form runtime features: - Yellow background is displayed for mandatory fields without value - Red background dis displayed for fields with validation errors - Error message is displayed in a balloon when fields with error has focus - Using balloons is now the default method of displaying errors - Removed balloon code form create site menu since its now handled automatically - An alternative to balloons are "error containers" (div with clickable red text labels focusing the field): setErrorContainer(divEl) - Its possible to setMultipleErrors(true) to display all the forms/fields errors in the "error container"/ballon. - Its possible to turn of the balloons and error containers complete by setting setErrorContainer(null) - js validation handlers no longer needs to handle the messages OR the css classes for mandatory & invalid 30344: Missing value check caused js undefined error 30346: Minor css form fixes 30347: THOR-126: S3 content store - do not swallow exceptions 30348: THOR-66: disable unused services/features 30349: THOR-137 F88: Add existing external user (from another network) checkpoint 30350: THOR-135 Is email address accepted by Alfresco. 46789: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35594: Fix merge issue 47930: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46762: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46768: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46769: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46778: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46780: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46786: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46791: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46792: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46808: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46809: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46819: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46829: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46839: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46842: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46844: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46846: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46847: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46876: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46877: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46878: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46879: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46880: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46881: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47947: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46737: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35288: Alfresco Cloud (from BRANCHES/V4.0) 35389: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30170: Thor branch based on Swift feature complete 30185: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 28973: THOR-1: verify ability to create DB schema programatically on AWS RDS (for MySQL & Oracle) 28999: THOR-3: Tenant Routing Data Source (dynamic tenant-aware DB connection pools) 29022: THOR-1: verify ability to create DB schema programatically on AWS RDS (for MySQL & Oracle) 29031: THOR-1: verify ability to create DB schema programatically on AWS RDS (for MySQL & Oracle) 30186: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: (3 conflicts resolved) 29116: THOR-3: Tenant Routing Data Source (dynamic tenant-aware DB connection pools) 29174: THOR-24 Set up new Alfresco AMP module project. 29186: THOR-25 Copy and refactor Account Service from SambaJAM 29193: ImporterComponent - prep for THOR-7 29198: THOR-7: Tenant Service API - Create Tenant (using separate DB schema) 29204: THOR-29 Account Type Registry 29234: THOR-7: Tenant Service API - Create Tenant (using separate DB schema) 29246: THOR-7: Tenant Service API - Create Tenant (using separate DB schema) 29251: THOR-30 Added AccountDAO interface along with two implementations: AccountDAOImpl (not implemented) which will manage Account data in an RDB via iBatis. AccountDAO_InMemory which manages AccountInfo in simple HashMaps for testing purposes only. 29258: THOR-28 29259: Addendum to THOR-25. Moved account-service spring config into a subfolder. (trivial) 35393: (RECORD ONLY) Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: - fix up classpath (remove mybatis 1.0.0 -> 1.0.1 and chemistry 0.4.0 -> 0.6.0) 35411: (RECORD ONLY) Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUD1: 35409: Merged HEAD to BRANCHES/DEV/V4.0-BUG-FIX: 35399: ALF-12874: Schema reference files are out of date. 35452: (RECORD ONLY) Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUD1: 34219: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/V4.0-BUG-FIX: 32096: THOR-429: Fix "MT: Thumbnail + Preview are not updated (after uploading new version)" 32125: THOR-429: Fix "MT: Thumbnail + Preview are not updated (after uploading new version)" 34220: Minor: follow-on to r34219 (ALF-11563) 34747: ALF-13262: adding missing indexes for new schema's (activiti-schema create) + schema patch for existing schema 35417: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/V4.0-BUG-FIX: (THOR-6 / ALF-13755) 29356: THOR-6: MT is configured (but not enabled) by default - will be auto-enabled when first tenant is created 29455: THOR-6: build test/fix 29471: THOR-6: build test/fix 35423: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/V4.0-BUG-FIX: (THOR-4 / ALF-13756) 29500: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 29501: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 29503: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 47949: Merged HEAD to BRANCHES/DEV/CONV_HEAD: 47914: Merge fix for org.alfresco.repo.cache.AbstractAsynchronouslyRefreshedCache<T> R 46078, 46079, 46121 47958: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46746: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35455: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30187: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29260: THOR: Initial Tenant Admin Service REST API - create, delete, get (list) web scripts 29356: THOR-6: MT is configured by default 29366: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29377: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29398: Refactoring of code to remove deprecation warnings. Replaced lots of object.field accesses with object.getField() calls.Trivial changes, but with so many warnings I can't see the wood for the trees. 29400: THOR-59: selectively disable certain test suites (for THOR dev build plan) 35456: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30188: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29442: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29453: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29455: THOR-76: track THOR build test failures and fix-up 29471: THOR-76: track THOR build test failures and fix-up 35459: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30189: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29473: Preliminary checkin for THOR-44. Created placeholder interface/impl/spring config for a new UserService. 29497: THOR-76: track THOR build test failures and fix-up ( LicenseComponentTest) 29500: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 29501: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 29503: THOR-4: Replace Tenant attributes with Tenant table (alf_tenant) 29511: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29512: Adding a new JUnit4 test class with an @Ignore'd test in it - to see how Bamboo reports these. 29514: THOR: Initial Tenant Admin Service REST API - create, delete, list web scripts 29515: THOR-59: selectively disable certain test suites (for THOR dev build plan) 29521: THOR-79 - mark AVM sitestore as unindexed 35461: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30190: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29533: THOR-59: exclude certain N/A tests 29555: THOR-76: track THOR build test failures 29630: Added ant build targets for Cloud Module and a new executable for the Alfresco devenv. 29664: THOR-76: exclude system test suites 29667: THOR-64: add initial support for tenant routing data source 29676: THOR-76: exclude intermittent ActionTrackingServiceImplTest (pending ALF-9773 & ALF-9774) 29677: THOR-80: MT-aware S3 content store 29678: THOR-80: MT-aware S3 content store 29680: THOR-80: MT-aware S3 content store 29693: THOR-80: MT-aware S3 content store 29694: THOR-80: MT-aware S3 content store 47959: CONV_HEAD: CLOUD-1348 - comment back in MultiTDemoTest.testDeleteAllTenants 47967: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46748: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35464: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30195: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29774: Refactor Account DAO and Service. Boost Tests. Add appropriate headers. 29776: THOR-76: exclude intermittent ActionTrackingServiceImplTest (pending ALF-9773 & ALF-9774) 29795: Implemented MyBatis-backed Account DAO: 29817: Move (and rename) user service from repository to thor 30196: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29827: THOR-69: TenantAdminDAO 29832: THOR-78: fix tenantEntityCache (shared) 29834: THOR-111: experimental config option for S3 content store to support flat root (ie. all tenant files in single folder) 29856: THOR updates 29857: THOR-76: exclude build components/projects 46761: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35478: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30198: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29869: THOR-92. BPMN2.0 workflow definition for account self-signup. 29871: THOR-93. REST API for self signup (and miscellaneous related items). 29882: THOR-102: Faster CreateTenant 29888: THOR-95. Placeholder email template for self-signup. 29889: Completion of THOR-95. Placeholder emails for self-signup. Added a 'you've already registered' template. 29896: THOR-89F100: Create User Foundation API… 29912: Fix issue where module believed it was still executed after delete tenant 29940: THOR-96. First cut of a signup email sender delegate. This will be refined later - probably both in this sprint and the next. 29966: Fixing InvitationServiceImplTest failing tests, which are failing because the email templates are not there. 29978: THOR-89: Switch tenant for person creation 29982: THOR-89: Fix multi-domain account creation test after review with Jan 29983: THOR-102: Faster CreateTenant 29985: THOR-90: F99 Is email address already registred foundation API 29991: THOR-99: Thor module build/packaging 29994: Changes for THOR-92, THOR-93 and THOR-96. 30199: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29995: THOR-93. Use the proper sspring config in the test case. 29996: THOR-99: Thor module build/packaging 29997: Consolidated DaveC's EmailAddressService and my EMailUtil into a single feature. 29998: Follow-on to previous check-in (29997). Deletion of now-unused folder. 30000: Blatant attempt to get svn r=30k. Removing some dead config. 30001: THOR-96. Ensure that we get a meaningful exception when attempting to activate an account with no pending workflow for that email. 30036: Resolve issues with tenant-independent user store - can now login via Share 30041: Package and auto deploy of license with Thor module 30048: Ensure that when a duplicate email prevents a workflow from creating an account, that the workflow still ends gracefully. 30049: Removing a dead class that I'd used to see how our Bamboo handles @Ignore(message=msg) @Test annotations. 30054: THOR-84 F82: List Accounts Foundation API 30067: THOR-87 List Accounts REST API. 30069: THOR-87. Completion of listAccounts REST API. Fixed the problems in the JUnit test case and tweaked the FTL slightly. 30071: Cosmetic changes as part of THOR-93. 30072: Oops. Broke a test case. Follow-on to previous (30071) check-in which cosmetically changed JSON as part of THOR-93. 30073: As part of THOR-93 (REST API signup) I have made the 2 webscripts usable without any authentication. 30074: Trivial fix to an error string. 30076: THOR-93. The account-activation.post webscript now includes the provided workflowInstanceId when identifying the ongoing workflow. 30077: Fix Email validator to allow for example domains 30202: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 30140: Refactor of account signup workflow 30142: No longer require email address for activation step of sign-up 30143: Remove use of task query in account signup workflow 30146: thor-share project structure 30147: Buildfix (removed modules not used by THOR) 30151: Incorporate already registered use case into account signup workflow 30152: Finally resolve license loading in Eclipse based tests 30203: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 30184: Build box fix as a result of not including certian components 30206: Fix blatant merge issues 47972: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46766: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35497: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/CLOUD1: 29723: THOR-31: MT-aware shared caches 29749: THOR-5: MT-aware immutable singletons 29762: THOR-31: MT-aware shared cache 46767: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35507: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30237: Merged BRANCHES/DEV/THOR0 to BRANCHES/DEV/THOR1: 29532: THOR-79 - add ability to disable Lucene indexes (so that IndexInfo / IndexInfoBackup files are not created per store per tenant) 29723: THOR-31: MT-aware shared caches 29749: THOR-5: MT-aware immutable singletons 29762: THOR-31: MT-aware shared cache 47973: CONV_HEAD: CLOUD-1348 - comment back in MultiTDemoTest tests (testNonSharedGroupDeletion & testSharedGroupDeletion) 47975: CONV_HEAD: CLOUD-1348 - comment back in FeedNotifierTest.testFailedNotifications 47988: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46775: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35531: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30449: F66: add option to configure a common "contentRootContainerPath" 30564: THOR-156: prep - consolidate runAsSystemTenant/runAsPrimaryTenant 35532: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30777: THOR-201: temporarily comment-out MultiTDemoTest.testDeleteArchiveAndRestoreContent (pending fix for THOR-201) 48008: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46844: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46895: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46903: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46907: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46922: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46974: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46991: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46992: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46994: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47107: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47265: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47267: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47272: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47277: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47284: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47286: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47289: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47292: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 48009: Merged DEV/CONV_V413 to DEV/CONV_HEAD 46801: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35602: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30513: Cloud Share module 30515: Fix issue with person replication between tenants. 30516: Slight mod to email validation web script response. 30518: Quick fix for workflow id generation in sign email 30534: THOR-163: Unable to get license file 30535: Fix Thor build process. 30536: Refine user's home site name and description 30539: THOR-96. When sending the signup email, execute the mail action asynchronously. 30542: Replace placeholder text in sign-up email 30543: Account Activation 46802: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35643: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30544: Account activation 30545: Account activation 30550: AMP build targets 30554: THOR-94. Cloud site invitation workflow. 30555: AMP build targets - added client side resources 48011: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 47056: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47087: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47228: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47271: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47297: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47299: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47300: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47301: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47304: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47328: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47330: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 47339: (RECORD ONLY) Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 48013: Merged DEV/CONV_V413 to DEV/CONV_HEAD (commiting the missing merge info for r48009) 46801: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35602: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30513: Cloud Share module 30515: Fix issue with person replication between tenants. 30516: Slight mod to email validation web script response. 30518: Quick fix for workflow id generation in sign email 30534: THOR-163: Unable to get license file 30535: Fix Thor build process. 30536: Refine user's home site name and description 30539: THOR-96. When sending the signup email, execute the mail action asynchronously. 30542: Replace placeholder text in sign-up email 30543: Account Activation 46802: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35643: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30544: Account activation 30545: Account activation 30550: AMP build targets 30554: THOR-94. Cloud site invitation workflow. 30555: AMP build targets - added client side resources 48015: Merged DEV/CONV_V413 to DEV/CONV_HEAD 46841: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35684: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30904: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30270 ALF-9492 Can now update task properties through the Workflow JavaScript API. ALF-10087 Fixed failing Multi-tenancy tests. 30288 ALF-9492 Can now update task properties through the Workflow JavaScript API. 30309 Fixed failing MultiTDemoTest and re-enabled. 30356 ALF-10117: JBPM workflows should be hidden. 30358 Build fix, fallout from ALF-10117 (JBPM workflows should be hidden) 30415 Added parseRootElement() method to Activiti's BPMNParseListener. 30452 ALF-10276: Reject flow didn't set bpm_assignee property properly 30563 Added tests to ensure multi-tenancy works and fixed several multi-tenancy issues in workflow. 30698 ALF-9541: Fixed HistoricTaskEntity update when TaskEntity is loaded from DB 30699 ALF-10084, ALF-10242. Fixed issues and added WorkflowService methods to get workflow instances without filtering by definition id. 30750 ALF-10197, Added the ability to auto-complete Start Tasks in Activiti. If a start task extends the bpm:activitiStartTask type or implements the bpm:endAutomatically aspect then the task will be ended as soon as the workflow instance is started. 30796 ALF-10374 Fixed failing MultiTDemoTest 30908: Add logging for failed email domain lookups: 30922: Rolling back .classpath changes to Data Model. 30930: Basic version of site invite working 30931: THOR-172: Switch Tenant via public API 30936: Allow for repo web scripts to switch to user's default tenant via -default- tenant id: 30937: Implementation of THOR-214. There is now a new repo webscript to retrieve signup status for a given {id, key} pair. 30938: Allow dev email address to be specified in properties file: 30945: THOR-221: Add (EntityLookup) cache to AccountDAO 30946: Build fix. Renaming a test infrastructure class so that it doesn't get picked up by the ant test targets. 30955: THOR-222. Added inviter first and last name to invitation-status.get webscript. 46843: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35694: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30997: Firefox scrollbars removed on "invitation" and "signup" pages (now using new helper method Alfresco.util.createYUIOverlay) 31001: Impl of THOR-223. Webscripts for getting pending invitations. 31002: Invite - redirect bug fixed, removed old code matching previous webscript api, email picker style fixes 31003: Addendum for THOR-223. I've added an explicit test to record the fact that pending-invitations.get to a non-existent site returns 200 and an empty collection rather than a 404. 31004: Adding REST-client .rcq files as part of THOR-223 46848: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35700: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 31014: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30999: ALF-9957 - MT: test and fix subscriptions (followers) 31020: Update invite email template to bring in line with wireframe and text 31021: Apply latest sanitized email blacklist: 31030: Fixed THOR-226 "DocLib "Detailed View" (default) does not list items - note: "Simple View" seems to be OK" 31033: THOR-228: Update aws sample file with quota config for cachingcontentstore 31036: Fixed THOR-236 "Webscript URL clash in signup" 31037: THOR-175: set and enforce per-tenant quota 31043: Fixed THOR-174 "F27: User can switch between networks they belong to" 46854: Merged from BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413 35725: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 31124: Fix for THOR-145. This check-in makes the Cloud Signup and Invitation workflows hidden within Share - users can't initiate them via "Start workflow..." 48016: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46793: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46795: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46796: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 48030: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46820: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35657: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30556: THOR-135F103: Is e-mail address accepted by Alfresco? 30562: Fixing a typo in the email-validation FTL. It was returning invalid JSON - no opening " on a string. 30569: THOR-156: switch to secondary tenant (initially via @@login) 30571: THOR-99: Thor build 48037: Merged BRANCHES/DEV/CONV_V413 to BRANCHES/DEV/CONV_HEAD: 46821: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 35659: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30586: THOR-166. I've added an additional check at the start of the signup workflow that checks if the email is blocked. 30587: THOR-163: S3ContentReader fails to getObjectDetails 30592: THOR-156: switch to secondary tenant (initially via @@login) 35660: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30607: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30208: Remaining commits for ALF-9510 30218: Fix build - add missing files 30254: Encryption related documentation, source code comments 30392: Fix for ALF-10205 30405: Fix for ALF-10189 30406: Fix for ALF-10189: part 2 - minor update 30613: THOR-148. The cloud test target was accidentally excluding *RestTest.java. 30613: THOR-148. The cloud test target was accidentally excluding *RestTest.java. 30614: Revert some of the additional email checks in registration process 30615: Set ignore patterns for build dir in thor module 30619: Merged HEAD to BRANCHES/DEV/THOR1: 30618: Additional test classes that allow for easier testing of Notifications (emails mostly). 30622: Ensure use of System user, not system user 30624: Removed deep merge info 30625: Switch off creation of missing people, use Admin instead of System 46824: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 46828: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: 48038: Merged DEV/CONV_V413 to DEV/CONV_HEAD (ui-only) 46830: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30737: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30736: ALF-6706 - MT: activities not generated (for tenants) 30738: Site invite (rough version, not finished) 30741: THOR-175: Set and enforce file space quota for tenant 30752: Site invite - added som padding to user suggestion list 30753: Disabling 2 tests while I fix them. 30758: THOR-172 F63: Switch Tenant via public REST API: 30764: Tweak to Activiti integration code to prevent it from trying to create person nodes for the System user. 30766: Implementation of THOR-196. Inviting multiple email addresses in a single call. 30769: Re-enable MultiTDemoTest 30775: Site invite 30776: THOR-172: Switch Tenant via public API 30785: Add tenant id to account info returned in Thor responses 48043: Merged DEV/CONV_V413 to DEV/CONV_HEAD 46831: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30813: Add Eclipse project for Thor-Share module: 30815: THOR-175: Set and enforce file space quota for tenant 30817: Switch network skeleton code and minor fixes 30818: Update Share Node Browser (at least for THOR) to allow option to retrieve "storeroot" via DB query 30826: Add distribute-solr to Thor builds 48045: Merged BRANCHES/DEV/CLOUD2 to BRANCHES/DEV/CONV_V413: Merged BRANCHES/DEV/THOR1 to BRANCHES/DEV/CLOUD1: 30737: (RECORD ONLY) Merged HEAD to BRANCHES/DEV/THOR1: 30736: ALF-6706 - MT: activities not generated (for tenants) 30738: Site invite (rough version, not finished) 30741: THOR-175: Set and enforce file space quota for tenant 30752: Site invite - added som padding to user suggestion list 30753: Disabling 2 tests while I fix them. 30758: THOR-172 F63: Switch Tenant via public REST API: 30764: Tweak to Activiti integration code to prevent it from trying to create person nodes for the System user. 30766: Implementation of THOR-196. Inviting multiple email addresses in a single call. 30769: Re-enable MultiTDemoTest 30775: Site invite 30776: THOR-172: Switch Tenant via public API 30785: Add tenant id to account info returned in Thor responses git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@48251 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
1816 lines
78 KiB
Java
1816 lines
78 KiB
Java
/*
|
||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||
*
|
||
* This file is part of Alfresco
|
||
*
|
||
* Alfresco is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU Lesser General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* Alfresco is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public License
|
||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
package org.alfresco.repo.tenant;
|
||
|
||
import java.io.InputStream;
|
||
import java.io.PrintWriter;
|
||
import java.io.Serializable;
|
||
import java.io.StringWriter;
|
||
import java.util.ArrayList;
|
||
import java.util.Arrays;
|
||
import java.util.Collection;
|
||
import java.util.HashMap;
|
||
import java.util.HashSet;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Set;
|
||
|
||
import junit.framework.TestCase;
|
||
|
||
import org.alfresco.error.AlfrescoRuntimeException;
|
||
import org.alfresco.model.ApplicationModel;
|
||
import org.alfresco.model.ContentModel;
|
||
import org.alfresco.query.PagingRequest;
|
||
import org.alfresco.repo.content.MimetypeMap;
|
||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||
import org.alfresco.repo.model.Repository;
|
||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||
import org.alfresco.repo.node.archive.RestoreNodeReport;
|
||
import org.alfresco.repo.node.index.FullIndexRecoveryComponent;
|
||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||
import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl;
|
||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||
import org.alfresco.service.cmr.model.FileFolderService;
|
||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||
import org.alfresco.service.cmr.repository.ContentService;
|
||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||
import org.alfresco.service.cmr.repository.NodeRef;
|
||
import org.alfresco.service.cmr.repository.NodeService;
|
||
import org.alfresco.service.cmr.repository.StoreRef;
|
||
import org.alfresco.service.cmr.search.CategoryService;
|
||
import org.alfresco.service.cmr.search.ResultSet;
|
||
import org.alfresco.service.cmr.search.SearchService;
|
||
import org.alfresco.service.cmr.security.AccessPermission;
|
||
import org.alfresco.service.cmr.security.AccessStatus;
|
||
import org.alfresco.service.cmr.security.AuthorityService;
|
||
import org.alfresco.service.cmr.security.AuthorityType;
|
||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||
import org.alfresco.service.cmr.security.OwnableService;
|
||
import org.alfresco.service.cmr.security.PermissionService;
|
||
import org.alfresco.service.cmr.security.PersonService;
|
||
import org.alfresco.service.cmr.security.PersonService.PersonInfo;
|
||
import org.alfresco.service.cmr.site.SiteInfo;
|
||
import org.alfresco.service.cmr.site.SiteService;
|
||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||
import org.alfresco.service.cmr.usage.UsageService;
|
||
import org.alfresco.service.namespace.NamespaceService;
|
||
import org.alfresco.service.namespace.QName;
|
||
import org.alfresco.service.transaction.TransactionService;
|
||
import org.alfresco.util.ApplicationContextHelper;
|
||
import org.apache.commons.logging.Log;
|
||
import org.apache.commons.logging.LogFactory;
|
||
import org.junit.FixMethodOrder;
|
||
import org.junit.runners.MethodSorters;
|
||
import org.springframework.context.ApplicationContext;
|
||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||
|
||
/**
|
||
* @author janv
|
||
* since 3.0
|
||
*/
|
||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||
public class MultiTDemoTest extends TestCase
|
||
{
|
||
private static Log logger = LogFactory.getLog(MultiTDemoTest.class);
|
||
|
||
private static ApplicationContext ctx = new ClassPathXmlApplicationContext(
|
||
new String[] {ApplicationContextHelper.CONFIG_LOCATIONS[0], "classpath:tenant/mt-*context.xml"}
|
||
);
|
||
|
||
private NodeService nodeService;
|
||
private NodeArchiveService nodeArchiveService;
|
||
private NamespaceService namespaceService;
|
||
private MutableAuthenticationService authenticationService;
|
||
private PersonService personService;
|
||
private SiteService siteService;
|
||
private SearchService searchService;
|
||
private ContentService contentService;
|
||
private PermissionService permissionService;
|
||
private OwnableService ownableService;
|
||
private TenantAdminService tenantAdminService;
|
||
private TenantService tenantService;
|
||
private AuthorityService authorityService;
|
||
private CategoryService categoryService;
|
||
private CheckOutCheckInService cociService;
|
||
private RepoAdminService repoAdminService;
|
||
private DictionaryService dictionaryService;
|
||
private UsageService usageService;
|
||
private TransactionService transactionService;
|
||
private FileFolderService fileFolderService;
|
||
private Repository repositoryHelper;
|
||
private FullIndexRecoveryComponent indexRecoverer;
|
||
|
||
public static int NUM_TENANTS = 2;
|
||
|
||
public static final String TEST_RUN = System.currentTimeMillis()+"";
|
||
public static final String TEST_TENANT_DOMAIN = TEST_RUN+".my.test";
|
||
public static final String TEST_TENANT_DOMAIN2 = TEST_TENANT_DOMAIN+"2";
|
||
|
||
public static List<String> tenants;
|
||
|
||
static
|
||
{
|
||
tenants = new ArrayList<String>(NUM_TENANTS);
|
||
for (int i = 1; i <= NUM_TENANTS; i++)
|
||
{
|
||
tenants.add(TEST_TENANT_DOMAIN+i);
|
||
}
|
||
}
|
||
|
||
public static final String ROOT_DIR = "./tenantstores";
|
||
|
||
public static final String DEFAULT_ADMIN_PW = "admin";
|
||
|
||
public static final String DEFAULT_GUEST_UN = "guest";
|
||
public static final String DEFAULT_GUEST_PW = "thiscanbeanything";
|
||
|
||
public static final String TEST_USER1 = "alice";
|
||
public static final String TEST_USER2 = "bob";
|
||
public static final String TEST_USER3 = "eve";
|
||
public static final String TEST_USER4 = "fred";
|
||
|
||
private static Set<StoreRef> DEFAULT_STORES = new HashSet<StoreRef>(Arrays.asList(new StoreRef[]
|
||
{
|
||
new StoreRef("workspace://lightWeightVersionStore"), new StoreRef("system://system"),
|
||
new StoreRef("workspace://version2Store"), new StoreRef("user://alfrescoUserStore"),
|
||
new StoreRef("workspace://SpacesStore"), new StoreRef("archive://SpacesStore")
|
||
}));
|
||
private static final int DEFAULT_STORE_COUNT = DEFAULT_STORES.size();
|
||
|
||
public static StoreRef SPACES_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||
|
||
|
||
public MultiTDemoTest()
|
||
{
|
||
super();
|
||
}
|
||
|
||
|
||
@Override
|
||
protected void setUp() throws Exception
|
||
{
|
||
super.setUp();
|
||
|
||
nodeService = (NodeService) ctx.getBean("NodeService");
|
||
nodeArchiveService = (NodeArchiveService) ctx.getBean("nodeArchiveService");
|
||
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
|
||
authenticationService = (MutableAuthenticationService) ctx.getBean("AuthenticationService");
|
||
tenantAdminService = (TenantAdminService) ctx.getBean("tenantAdminService");
|
||
tenantService = (TenantService) ctx.getBean("tenantService");
|
||
personService = (PersonService) ctx.getBean("PersonService");
|
||
searchService = (SearchService) ctx.getBean("SearchService");
|
||
contentService = (ContentService) ctx.getBean("ContentService");
|
||
permissionService = (PermissionService) ctx.getBean("PermissionService");
|
||
ownableService = (OwnableService) ctx.getBean("OwnableService");
|
||
authorityService = (AuthorityService) ctx.getBean("AuthorityService");
|
||
categoryService = (CategoryService) ctx.getBean("CategoryService");
|
||
cociService = (CheckOutCheckInService) ctx.getBean("CheckoutCheckinService");
|
||
repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService");
|
||
dictionaryService = (DictionaryService) ctx.getBean("DictionaryService");
|
||
usageService = (UsageService) ctx.getBean("usageService");
|
||
transactionService = (TransactionService) ctx.getBean("TransactionService");
|
||
fileFolderService = (FileFolderService) ctx.getBean("FileFolderService");
|
||
ownableService = (OwnableService) ctx.getBean("OwnableService");
|
||
repositoryHelper = (Repository) ctx.getBean("repositoryHelper");
|
||
siteService = (SiteService) ctx.getBean("SiteService");
|
||
|
||
ChildApplicationContextFactory luceneSubSystem = (ChildApplicationContextFactory) ctx.getBean("lucene");
|
||
indexRecoverer = (FullIndexRecoveryComponent) luceneSubSystem.getApplicationContext().getBean("search.indexRecoveryComponent");
|
||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); // authenticate as super-admin
|
||
|
||
createTenants();
|
||
createUsers();
|
||
}
|
||
|
||
@Override
|
||
protected void tearDown() throws Exception
|
||
{
|
||
super.tearDown();
|
||
}
|
||
|
||
private void createTenants()
|
||
{
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
createTenant(tenantDomain);
|
||
}
|
||
}
|
||
|
||
private void createTenant(final String tenantDomain)
|
||
{
|
||
// create tenants (if not already created)
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
if (! tenantAdminService.existsTenant(tenantDomain))
|
||
{
|
||
//tenantAdminService.createTenant(tenantDomain, DEFAULT_ADMIN_PW.toCharArray(), ROOT_DIR + "/" + tenantDomain);
|
||
tenantAdminService.createTenant(tenantDomain, (DEFAULT_ADMIN_PW+" "+tenantDomain).toCharArray(), null); // use default root dir
|
||
|
||
logger.info("Created tenant " + tenantDomain);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getSystemUserName());
|
||
}
|
||
|
||
private void deleteTenant(final String tenantDomain)
|
||
{
|
||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Object>()
|
||
{
|
||
public Object execute() throws Throwable
|
||
{
|
||
// delete tenant (if it exists)
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
if (tenantAdminService.existsTenant(tenantDomain))
|
||
{
|
||
tenantAdminService.deleteTenant(tenantDomain);
|
||
|
||
logger.info("Deleted tenant " + tenantDomain);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getSystemUserName());
|
||
return null;
|
||
}
|
||
});
|
||
}
|
||
|
||
private void createUsers()
|
||
{
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
createUser(TEST_USER1, tenantDomain, TEST_USER1+" "+tenantDomain);
|
||
createUser(TEST_USER2, tenantDomain, TEST_USER2+" "+tenantDomain);
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
createUser(TEST_USER3, tenantDomain, TEST_USER3+" "+tenantDomain);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
// note: needs to come before test10CreateCategories & test15COCIandSearch ?
|
||
public synchronized void test00_ALF_17681() throws Exception
|
||
{
|
||
// The issue was found on Lucene
|
||
final String tenantDomain = TEST_RUN+".alf17681";
|
||
final String query = "PATH:\"/app:company_home/app:dictionary\"";
|
||
|
||
// Create tenant
|
||
createTenant(tenantDomain);
|
||
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
// Search for Data dictionary by tenant admin
|
||
int count = searchForDataDictionary(tenantAdminName, query);
|
||
|
||
assertEquals("Data dictionary should be found for tenant. ", 1, count);
|
||
|
||
indexRecoverer.setRecoveryMode(FullIndexRecoveryComponent.RecoveryMode.FULL.name());
|
||
|
||
// reindex
|
||
Thread reindexThread = new Thread()
|
||
{
|
||
public void run()
|
||
{
|
||
indexRecoverer.reindex();
|
||
}
|
||
};
|
||
|
||
reindexThread.start();
|
||
|
||
// must allow the rebuild to complete or the test after this one will fail to validate their indexes
|
||
// - as they now will be deleted.
|
||
reindexThread.join();
|
||
|
||
// wait a bit and then terminate
|
||
wait(20000);
|
||
indexRecoverer.setShutdown(true);
|
||
wait(20000);
|
||
|
||
// Search for Data dictionary by tenant admin
|
||
int countAfter = searchForDataDictionary(tenantAdminName, query);
|
||
|
||
assertEquals("Data dictionary should be found for tenant after FULL reindex. ", 1, countAfter);
|
||
}
|
||
|
||
/*
|
||
public void test00_Setup() throws Throwable
|
||
{
|
||
// test common setup (see "setUp")
|
||
}
|
||
*/
|
||
|
||
public void test01CreateTenants() throws Throwable
|
||
{
|
||
// ignore common setup - test here explicitly
|
||
|
||
logger.info("Create tenants");
|
||
|
||
final String tenantDomain1 = TEST_RUN+".one.createTenant";
|
||
final String tenantDomain2 = TEST_RUN+".two.createTenant";
|
||
|
||
String[] tenantDomains = new String[] {tenantDomain1, tenantDomain2 };
|
||
|
||
for (final String tenantDomain : tenantDomains)
|
||
{
|
||
createTenant(tenantDomain);
|
||
}
|
||
|
||
// check default (super-tenant) domain
|
||
|
||
List<PersonInfo> persons = personService.getPeople(null, true, null, new PagingRequest(0, Integer.MAX_VALUE, null)).getPage();
|
||
|
||
//assertEquals(2, personRefs.size()); // super-tenant: admin, guest (note: checking for 2 assumes that this test is run in a fresh bootstrap env)
|
||
|
||
for (PersonInfo person : persons)
|
||
{
|
||
String userName = person.getUserName();
|
||
for (final String tenantDomain : tenantDomains)
|
||
{
|
||
assertFalse("Unexpected (tenant) user: "+userName, userName.endsWith(tenantDomain));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private void deleteTestAuthoritiesForTenant(final String[] uniqueGroupNames, final String userName)
|
||
{
|
||
// Check deletion for tenant1
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
// find person
|
||
NodeRef personNodeRef = personService.getPerson(userName);
|
||
NodeRef homeSpaceRef = (NodeRef)nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||
assertNotNull(homeSpaceRef);
|
||
|
||
// Delete authorities
|
||
for (int i = 0; i < uniqueGroupNames.length; i++)
|
||
{
|
||
authorityService.deleteAuthority("GROUP_" + uniqueGroupNames[i]);
|
||
}
|
||
return null;
|
||
}
|
||
}, userName);
|
||
}
|
||
private void createTestAuthoritiesForTenant(final String[] uniqueGroupNames, final String userName)
|
||
{
|
||
// Create groups for tenant
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
// find person
|
||
NodeRef personNodeRef = personService.getPerson(userName);
|
||
NodeRef homeSpaceRef = (NodeRef)nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||
assertNotNull(homeSpaceRef);
|
||
|
||
for (int i = 0; i < uniqueGroupNames.length; i++)
|
||
{
|
||
authorityService.createAuthority(AuthorityType.GROUP, uniqueGroupNames[i]);
|
||
permissionService.setPermission(homeSpaceRef, "GROUP_" + uniqueGroupNames[i], "Consumer", true);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, userName);
|
||
}
|
||
|
||
private void checkTestAuthoritiesPresence(final String[] uniqueGroupNames, final String userName, final boolean shouldPresent)
|
||
{
|
||
// Check that created permissions are not visible to tenant 2
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef personNodeRef = personService.getPerson(userName);
|
||
NodeRef homeSpaceRef = (NodeRef)nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||
Set<AccessPermission> perms = permissionService.getAllSetPermissions(homeSpaceRef);
|
||
Set<String> auths = authorityService.getAllAuthorities(AuthorityType.GROUP);
|
||
|
||
for (int i = 0; i < uniqueGroupNames.length; i++)
|
||
{
|
||
AccessPermission toCheck = new AccessPermissionImpl("Consumer", AccessStatus.ALLOWED, "GROUP_" + uniqueGroupNames[i], 0);
|
||
if (shouldPresent)
|
||
{
|
||
assertTrue(auths.contains("GROUP_" + uniqueGroupNames[i]));
|
||
assertTrue(perms.contains(toCheck));
|
||
}
|
||
else
|
||
{
|
||
assertTrue(!auths.contains("GROUP_" + uniqueGroupNames[i]));
|
||
assertTrue(!perms.contains(toCheck));
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, userName);
|
||
}
|
||
|
||
private void createGroup(String shortName, String parentShortName)
|
||
{
|
||
// create new Group using authority Service
|
||
String groupName = this.authorityService.getName(AuthorityType.GROUP, shortName);
|
||
if (this.authorityService.authorityExists(groupName) == false)
|
||
{
|
||
String parentGroupName = null;
|
||
if (parentShortName != null)
|
||
{
|
||
parentGroupName = this.authorityService.getName(AuthorityType.GROUP, parentShortName);
|
||
if (this.authorityService.authorityExists(parentGroupName) == false)
|
||
{
|
||
logger.warn("Parent group does not exist: " + parentShortName);
|
||
return;
|
||
}
|
||
}
|
||
|
||
this.authorityService.createAuthority(AuthorityType.GROUP, shortName);
|
||
|
||
if (parentGroupName != null)
|
||
{
|
||
addToGroup(parentShortName, groupName);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
logger.warn("Group already exists: " + shortName);
|
||
}
|
||
}
|
||
|
||
private void addToGroup(String parentGroupShortName, String authorityName)
|
||
{
|
||
String parentGroupName = this.authorityService.getName(AuthorityType.GROUP, parentGroupShortName);
|
||
authorityService.addAuthority(parentGroupName, authorityName);
|
||
}
|
||
|
||
private NodeRef createUser(String baseUserName, String tenantDomain, String password)
|
||
{
|
||
String userName = tenantService.getDomainUser(baseUserName, tenantDomain);
|
||
|
||
NodeRef personNodeRef = null;
|
||
|
||
if (! this.authenticationService.authenticationExists(userName))
|
||
{
|
||
NodeRef baseHomeFolder = getUserHomesNodeRef(SPACES_STORE);
|
||
|
||
// Create the users home folder
|
||
NodeRef homeFolder = createHomeSpaceFolderNode(
|
||
baseHomeFolder,
|
||
baseUserName,
|
||
userName);
|
||
|
||
// Create the authentication
|
||
this.authenticationService.createAuthentication(userName, password.toCharArray());
|
||
|
||
// Create the person
|
||
Map<QName, Serializable> personProperties = new HashMap<QName, Serializable>();
|
||
personProperties.put(ContentModel.PROP_USERNAME, userName);
|
||
personProperties.put(ContentModel.PROP_HOMEFOLDER, homeFolder);
|
||
personProperties.put(ContentModel.PROP_FIRSTNAME, baseUserName);
|
||
personProperties.put(ContentModel.PROP_LASTNAME, baseUserName+"-"+tenantDomain); // add domain suffix here for demo only
|
||
personProperties.put(ContentModel.PROP_EMAIL, userName);
|
||
|
||
personNodeRef = this.personService.createPerson(personProperties);
|
||
|
||
// ensure the user can access their own Person object
|
||
this.permissionService.setPermission(personNodeRef, userName, permissionService.getAllPermission(), true);
|
||
|
||
NodeRef checkHomeSpaceRef = (NodeRef)nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||
assertNotNull(checkHomeSpaceRef);
|
||
|
||
logger.info("Created user " + userName);
|
||
}
|
||
else
|
||
{
|
||
personNodeRef = personService.getPerson(userName);
|
||
|
||
logger.info("Found existing user " + userName);
|
||
}
|
||
|
||
return personNodeRef;
|
||
}
|
||
|
||
private void loginLogoutUser(String username, String password)
|
||
{
|
||
// authenticate via the authentication service
|
||
authenticationService.authenticate(username, password.toCharArray());
|
||
|
||
// set the user name as stored by the back end
|
||
username = authenticationService.getCurrentUserName();
|
||
|
||
NodeRef personRef = personService.getPerson(username);
|
||
NodeRef homeSpaceRef = (NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER);
|
||
|
||
// check that the home space node exists - else user cannot login
|
||
if (nodeService.exists(homeSpaceRef) == false)
|
||
{
|
||
throw new InvalidNodeRefException(homeSpaceRef);
|
||
}
|
||
|
||
// logout
|
||
authenticationService.clearCurrentSecurityContext();
|
||
}
|
||
|
||
private NodeRef getUserHomesNodeRef(StoreRef storeRef)
|
||
{
|
||
// get the "User Homes" location
|
||
return findFolderNodeRef(storeRef, "/app:company_home/app:user_homes");
|
||
}
|
||
|
||
private NodeRef getWebClientExtensionNodeRef(StoreRef storeRef)
|
||
{
|
||
// get the "Web Client Extensions" location
|
||
return findFolderNodeRef(storeRef, "/app:company_home/app:dictionary/app:webclient_extension");
|
||
}
|
||
|
||
private NodeRef findFolderNodeRef(StoreRef storeRef, String folderXPath)
|
||
{
|
||
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
|
||
|
||
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, folderXPath, null, namespaceService, false);
|
||
|
||
NodeRef folderNodeRef = null;
|
||
if (nodeRefs.size() != 1)
|
||
{
|
||
throw new AlfrescoRuntimeException("Cannot find folder location: " + folderXPath);
|
||
}
|
||
else
|
||
{
|
||
folderNodeRef = nodeRefs.get(0);
|
||
}
|
||
return folderNodeRef;
|
||
}
|
||
|
||
private NodeRef createFolderNode(NodeRef parentFolderNodeRef, String nameValue)
|
||
{
|
||
if (nameValue != null)
|
||
{
|
||
Map<QName, Serializable> folderProps = new HashMap<QName, Serializable>();
|
||
folderProps.put(ContentModel.PROP_NAME, nameValue);
|
||
|
||
return this.nodeService.createNode(
|
||
parentFolderNodeRef,
|
||
ContentModel.ASSOC_CONTAINS,
|
||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, nameValue),
|
||
ContentModel.TYPE_FOLDER,
|
||
folderProps).getChildRef();
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private NodeRef createCategory(StoreRef storeRef, NodeRef parentCategoryRef, String name, String description)
|
||
{
|
||
// create category using categoryservice
|
||
NodeRef ref;
|
||
if (parentCategoryRef == null)
|
||
{
|
||
ref = this.categoryService.createRootCategory(storeRef, ContentModel.ASPECT_GEN_CLASSIFIABLE, name);
|
||
}
|
||
else
|
||
{
|
||
ref = categoryService.createCategory(parentCategoryRef, name);
|
||
}
|
||
|
||
// apply the titled aspect - for description
|
||
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
|
||
titledProps.put(ContentModel.PROP_DESCRIPTION, description);
|
||
this.nodeService.addAspect(ref, ContentModel.ASPECT_TITLED, titledProps);
|
||
|
||
return ref;
|
||
}
|
||
|
||
private NodeRef createHomeSpaceFolderNode(NodeRef folderNodeRef, String spaceName, String userName)
|
||
{
|
||
if (spaceName != null)
|
||
{
|
||
Map<QName, Serializable> folderProps = new HashMap<QName, Serializable>();
|
||
folderProps.put(ContentModel.PROP_NAME, spaceName);
|
||
|
||
NodeRef nodeRef = this.nodeService.createNode(
|
||
folderNodeRef,
|
||
ContentModel.ASSOC_CONTAINS,
|
||
QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, spaceName),
|
||
ContentModel.TYPE_FOLDER,
|
||
folderProps).getChildRef();
|
||
|
||
// apply the uifacets aspect - icon and title props
|
||
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(3);
|
||
uiFacetsProps.put(ApplicationModel.PROP_ICON, "space-icon-default");
|
||
uiFacetsProps.put(ContentModel.PROP_TITLE, spaceName);
|
||
this.nodeService.addAspect(nodeRef, ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
|
||
|
||
setupHomeSpacePermissions(nodeRef, userName);
|
||
|
||
return nodeRef;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private void setupHomeSpacePermissions(NodeRef homeSpaceRef, String userName)
|
||
{
|
||
// Admin Authority has full permissions by default (automatic - set in the permission config)
|
||
// give full permissions to the new user
|
||
this.permissionService.setPermission(homeSpaceRef, userName, permissionService.getAllPermission(), true);
|
||
|
||
// by default other users will only have GUEST access to the space contents
|
||
String permission = "Consumer";
|
||
|
||
if (permission != null && permission.length() != 0)
|
||
{
|
||
this.permissionService.setPermission(homeSpaceRef, permissionService.getAllAuthorities(), permission, true);
|
||
}
|
||
|
||
// the new user is the OWNER of their own space and always has full permissions
|
||
this.ownableService.setOwner(homeSpaceRef, userName);
|
||
this.permissionService.setPermission(homeSpaceRef, permissionService.getOwnerAuthority(), permissionService.getAllPermission(), true);
|
||
|
||
// now detach (if we did this first we could not set any permissions!)
|
||
this.permissionService.setInheritParentPermissions(homeSpaceRef, false);
|
||
}
|
||
|
||
private NodeRef getHomeSpaceFolderNode(String userName)
|
||
{
|
||
return (NodeRef)this.nodeService.getProperty(personService.getPerson(userName), ContentModel.PROP_HOMEFOLDER);
|
||
}
|
||
|
||
private NodeRef addContent(NodeRef spaceRef, String name, String textData, String mimeType)
|
||
{
|
||
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>();
|
||
contentProps.put(ContentModel.PROP_NAME, name);
|
||
|
||
ChildAssociationRef association = nodeService.createNode(spaceRef,
|
||
ContentModel.ASSOC_CONTAINS,
|
||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name),
|
||
ContentModel.TYPE_CONTENT,
|
||
contentProps);
|
||
|
||
NodeRef content = association.getChildRef();
|
||
|
||
// add titled aspect (for Web Client display)
|
||
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>();
|
||
titledProps.put(ContentModel.PROP_TITLE, name);
|
||
titledProps.put(ContentModel.PROP_DESCRIPTION, name);
|
||
this.nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps);
|
||
|
||
ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
|
||
|
||
writer.setMimetype(mimeType);
|
||
writer.setEncoding("UTF-8");
|
||
|
||
writer.putContent(textData);
|
||
|
||
return content;
|
||
}
|
||
|
||
private NodeRef addContent(NodeRef spaceRef, String name, InputStream is, String mimeType)
|
||
{
|
||
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>();
|
||
contentProps.put(ContentModel.PROP_NAME, name);
|
||
|
||
ChildAssociationRef association = nodeService.createNode(spaceRef,
|
||
ContentModel.ASSOC_CONTAINS,
|
||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name),
|
||
ContentModel.TYPE_CONTENT,
|
||
contentProps);
|
||
|
||
NodeRef content = association.getChildRef();
|
||
|
||
// add titled aspect (for Web Client display)
|
||
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>();
|
||
titledProps.put(ContentModel.PROP_TITLE, name);
|
||
titledProps.put(ContentModel.PROP_DESCRIPTION, name);
|
||
this.nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps);
|
||
|
||
ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
|
||
|
||
writer.setMimetype(mimeType);
|
||
writer.setEncoding("UTF-8");
|
||
|
||
writer.putContent(is);
|
||
|
||
return content;
|
||
}
|
||
|
||
private SiteInfo createSite(String siteId)
|
||
{
|
||
SiteInfo siteInfo = siteService.createSite(null, siteId, "title - "+siteId, "description - "+siteId, SiteVisibility.PRIVATE);
|
||
|
||
// ensure that the Document Library folder is pre-created so that test code can start creating content straight away.
|
||
// At the time of writing V4.1 does not create this folder automatically, but Thor does.
|
||
NodeRef result = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY);
|
||
if (result == null)
|
||
{
|
||
result = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
|
||
}
|
||
|
||
return siteInfo;
|
||
}
|
||
|
||
public void test02NonSharedGroupDeletion()
|
||
{
|
||
// ignore common setup - test here explicitly
|
||
|
||
final String tenantDomain1 = TEST_RUN+".groupdel1";
|
||
final String tenantDomain2 = TEST_RUN+".groupdel2";
|
||
|
||
try
|
||
{
|
||
final String[] tenantUniqueGroupNames = new String[10];
|
||
final String[] superadminUniqueGroupNames = new String[10];
|
||
for (int i = 0; i < tenantUniqueGroupNames.length; i++)
|
||
{
|
||
tenantUniqueGroupNames[i] = TEST_RUN + "test_group" + i;
|
||
superadminUniqueGroupNames[i] = TEST_RUN + "test_group_sa" + i;
|
||
}
|
||
|
||
clearUsage(AuthenticationUtil.getAdminUserName());
|
||
|
||
createTenant(tenantDomain1);
|
||
createTenant(tenantDomain2);
|
||
|
||
final String tenantAdminName1 = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain1);
|
||
final String tenantAdminName2 = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain2);
|
||
final String superAdmin = "admin";
|
||
|
||
// Create test authorities that are visible only to tenant1
|
||
clearUsage(tenantDomain1);
|
||
createTestAuthoritiesForTenant(tenantUniqueGroupNames, tenantAdminName1);
|
||
// Check that tenant1's authorities are visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(tenantUniqueGroupNames, tenantAdminName1, true);
|
||
// Check that tenant1's authorities are not visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(tenantUniqueGroupNames, tenantAdminName2, false);
|
||
// Check that tenant1's authorities are not visible to super-admin
|
||
checkTestAuthoritiesPresence(tenantUniqueGroupNames, superAdmin, false);
|
||
|
||
|
||
// Create test authorities that are visible only to super-admin
|
||
createTestAuthoritiesForTenant(superadminUniqueGroupNames, superAdmin);
|
||
// Check that super-admin's authorities are not visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(superadminUniqueGroupNames, tenantAdminName1, false);
|
||
// Check that super-admin's authorities are not visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(superadminUniqueGroupNames, tenantAdminName2, false);
|
||
// Check that super-admin's authorities are visible to super-admin
|
||
checkTestAuthoritiesPresence(superadminUniqueGroupNames, superAdmin, true);
|
||
|
||
|
||
// Delete tenant1's authorities
|
||
clearUsage(tenantDomain1);
|
||
deleteTestAuthoritiesForTenant(tenantUniqueGroupNames, tenantAdminName1);
|
||
// Check that tenant1's authorities are not visible to tenant1
|
||
checkTestAuthoritiesPresence(tenantUniqueGroupNames, tenantAdminName1, false);
|
||
|
||
// Delete super-admin's authorities
|
||
deleteTestAuthoritiesForTenant(superadminUniqueGroupNames, superAdmin);
|
||
// Check that super-admin's authorities are not visible to super-admin
|
||
checkTestAuthoritiesPresence(superadminUniqueGroupNames, superAdmin, false);
|
||
}
|
||
finally
|
||
{
|
||
deleteTenant(tenantDomain1);
|
||
deleteTenant(tenantDomain2);
|
||
}
|
||
}
|
||
|
||
public void test03SharedGroupDeletion()
|
||
{
|
||
// ignore common setup - test here explicitly
|
||
|
||
final String tenantDomain1 = TEST_RUN+".groupdel3";
|
||
final String tenantDomain2 = TEST_RUN+".groupdel4";
|
||
|
||
try
|
||
{
|
||
final String[] commonTenantUniqueGroupNames = new String[10];
|
||
for (int i = 0; i < commonTenantUniqueGroupNames.length; i++)
|
||
{
|
||
commonTenantUniqueGroupNames[i] = TEST_RUN + "test_group" + i;
|
||
}
|
||
|
||
clearUsage(AuthenticationUtil.getAdminUserName());
|
||
|
||
createTenant(tenantDomain1);
|
||
createTenant(tenantDomain2);
|
||
|
||
final String tenantAdminName1 = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain1);
|
||
final String tenantAdminName2 = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain2);
|
||
final String superAdmin = "admin";
|
||
|
||
// Create test common authorities for tenant1
|
||
clearUsage(tenantDomain1);
|
||
createTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName1);
|
||
// Create test common authorities for tenant2
|
||
clearUsage(tenantDomain2);
|
||
createTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName2);
|
||
// Create test common authorities for super-admin
|
||
createTestAuthoritiesForTenant(commonTenantUniqueGroupNames, superAdmin);
|
||
|
||
// Check that authorities are visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName1, true);
|
||
// Check that authorities are visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName2, true);
|
||
// Check that authorities are visible to super-admin
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, superAdmin, true);
|
||
|
||
// Delete tenant1's authorities
|
||
clearUsage(tenantDomain1);
|
||
deleteTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName1);
|
||
// Check that authorities are not visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName1, false);
|
||
// Check that authorities are visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName2, true);
|
||
// Check that authorities are visible to super-admin
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, superAdmin, true);
|
||
|
||
// Create test common authorities for tenant1
|
||
clearUsage(tenantDomain1);
|
||
createTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName1);
|
||
// Delete tenant2's authorities
|
||
clearUsage(tenantDomain2);
|
||
deleteTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName2);
|
||
// Check that authorities are visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName1, true);
|
||
// Check that authorities are not visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName2, false);
|
||
// Check that authorities are visible to super-admin
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, superAdmin, true);
|
||
|
||
// Create test common authorities for tenant2
|
||
clearUsage(tenantDomain2);
|
||
createTestAuthoritiesForTenant(commonTenantUniqueGroupNames, tenantAdminName2);
|
||
// Delete super-admin's authorities
|
||
deleteTestAuthoritiesForTenant(commonTenantUniqueGroupNames, superAdmin);
|
||
// Check that authorities are visible to tenant1
|
||
clearUsage(tenantDomain1);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName1, true);
|
||
// Check that authorities are visible to tenant2
|
||
clearUsage(tenantDomain2);
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, tenantAdminName2, true);
|
||
// Check that authorities are not visible to super-admin
|
||
checkTestAuthoritiesPresence(commonTenantUniqueGroupNames, superAdmin, false);
|
||
}
|
||
finally
|
||
{
|
||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||
|
||
deleteTenant(tenantDomain1);
|
||
deleteTenant(tenantDomain2);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public void test04_ETHREEOH_2015()
|
||
{
|
||
// ignore common setup - test here explicitly
|
||
|
||
final String tenantDomain1 = TEST_RUN+".one.ethreeoh2015";
|
||
final String tenantDomain2 = TEST_RUN+".two.ethreeoh2015";
|
||
|
||
clearUsage(AuthenticationUtil.getAdminUserName());
|
||
|
||
createTenant(tenantDomain1);
|
||
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain1);
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
createUser(TEST_USER1, tenantDomain1, TEST_USER1+" "+tenantDomain1);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
|
||
createTenant(tenantDomain2);
|
||
}
|
||
|
||
private void clearUsage(String userName)
|
||
{
|
||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); // authenticate as super-admin
|
||
|
||
// find person
|
||
NodeRef personNodeRef = personService.getPerson(userName);
|
||
// clear user usage
|
||
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT, null);
|
||
usageService.deleteDeltas(personNodeRef);
|
||
}
|
||
|
||
|
||
public void test05ValidateUsers() throws Throwable
|
||
{
|
||
// use common setup
|
||
logger.info("Validate demo users");
|
||
|
||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
List<PersonInfo> persons = personService.getPeople(null, true, null, new PagingRequest(0, Integer.MAX_VALUE, null)).getPage();
|
||
//assertEquals(2, personRefs.size()); // super-tenant: admin, guest (note: checking for 2 assumes that this test is run in a fresh bootstrap env)
|
||
for (PersonInfo person : persons)
|
||
{
|
||
String userName = person.getUserName();
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
assertFalse("Unexpected (tenant) user: "+userName, userName.endsWith(tenantDomain));
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getAdminUserName());
|
||
|
||
try
|
||
{
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
List<PersonInfo> persons = personService.getPeople(null, null, null, new PagingRequest(0, Integer.MAX_VALUE, null)).getPage();
|
||
|
||
for (PersonInfo person : persons)
|
||
{
|
||
NodeRef personRef = person.getNodeRef();
|
||
|
||
String userName = (String)nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
|
||
assertTrue(userName.endsWith(tenantDomain));
|
||
|
||
logger.info("Validate users: get all people - found user: "+userName);
|
||
|
||
NodeRef homeSpaceRef = (NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER);
|
||
assertNotNull(homeSpaceRef);
|
||
}
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
assertEquals(5, persons.size()); // admin@tenant, guest@tenant, alice@tenant, bob@tenant, eve@tenant
|
||
}
|
||
else
|
||
{
|
||
assertEquals(4, persons.size()); // admin@tenant, guest@tenant, alice@tenant, bob@tenant
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
catch (Throwable t)
|
||
{
|
||
StringWriter stackTrace = new StringWriter();
|
||
t.printStackTrace(new PrintWriter(stackTrace));
|
||
System.err.println(stackTrace.toString());
|
||
throw t;
|
||
}
|
||
}
|
||
|
||
public void test06LoginTenantUsers() throws Throwable
|
||
{
|
||
// use common setup
|
||
logger.info("Login tenant users");
|
||
|
||
try
|
||
{
|
||
AuthenticationUtil.clearCurrentSecurityContext();
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
loginLogoutUser(tenantService.getDomainUser(TEST_USER1, tenantDomain), TEST_USER1+" "+tenantDomain);
|
||
|
||
loginLogoutUser(tenantService.getDomainUser(TEST_USER2, tenantDomain), TEST_USER2+" "+tenantDomain);
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
loginLogoutUser(tenantService.getDomainUser(TEST_USER3, tenantDomain), TEST_USER3+" "+tenantDomain);
|
||
}
|
||
}
|
||
}
|
||
catch (Throwable t)
|
||
{
|
||
StringWriter stackTrace = new StringWriter();
|
||
t.printStackTrace(new PrintWriter(stackTrace));
|
||
System.err.println(stackTrace.toString());
|
||
throw t;
|
||
}
|
||
}
|
||
|
||
public void test07LoginTenantGuests() throws Throwable
|
||
{
|
||
logger.info("Login tenant guests");
|
||
|
||
try
|
||
{
|
||
AuthenticationUtil.clearCurrentSecurityContext();
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
loginLogoutUser(tenantService.getDomainUser(DEFAULT_GUEST_UN, tenantDomain), DEFAULT_GUEST_UN);
|
||
}
|
||
}
|
||
catch (Throwable t)
|
||
{
|
||
StringWriter stackTrace = new StringWriter();
|
||
t.printStackTrace(new PrintWriter(stackTrace));
|
||
System.err.println(stackTrace.toString());
|
||
throw t;
|
||
}
|
||
}
|
||
|
||
public void test08LoginTenantAdmin() throws Throwable
|
||
{
|
||
logger.info("Login tenant admins");
|
||
|
||
try
|
||
{
|
||
AuthenticationUtil.clearCurrentSecurityContext();
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
loginLogoutUser(tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain), DEFAULT_ADMIN_PW+" "+tenantDomain);
|
||
}
|
||
}
|
||
catch (Throwable t)
|
||
{
|
||
StringWriter stackTrace = new StringWriter();
|
||
t.printStackTrace(new PrintWriter(stackTrace));
|
||
System.err.println(stackTrace.toString());
|
||
throw t;
|
||
}
|
||
}
|
||
|
||
public void test09CreateGroups()
|
||
{
|
||
logger.info("Create demo groups");
|
||
|
||
assertTrue(tenants.size() > 0);
|
||
|
||
final int rootGrpsOrigCnt = TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Integer>()
|
||
{
|
||
public Integer doWork() throws Exception
|
||
{
|
||
return authorityService.getAllRootAuthorities(AuthorityType.GROUP).size();
|
||
}
|
||
}, tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenants.get(0)));
|
||
|
||
// create groups and add users
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
createGroup("GrpA", null);
|
||
createGroup("SubGrpA", "GrpA");
|
||
|
||
createGroup("GrpB", null);
|
||
|
||
createGroup("GrpC", null);
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
createGroup("SubGrpC", "GrpC");
|
||
}
|
||
|
||
createGroup("GrpD", null);
|
||
addToGroup("GrpD", tenantAdminName);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
|
||
// check groups/users
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
Set<String> rootGrps = authorityService.getAllRootAuthorities(AuthorityType.GROUP);
|
||
assertEquals(rootGrpsOrigCnt+4, rootGrps.size());
|
||
|
||
Set<String> auths = authorityService.getContainedAuthorities(null, "GROUP_GrpA", true);
|
||
assertEquals(1, auths.size());
|
||
|
||
auths = authorityService.getContainedAuthorities(null, "GROUP_GrpB", true);
|
||
assertEquals(0, auths.size());
|
||
|
||
auths = authorityService.getContainedAuthorities(null, "GROUP_GrpC", true);
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
assertEquals(1, auths.size());
|
||
}
|
||
else
|
||
{
|
||
assertEquals(0, auths.size());
|
||
}
|
||
|
||
auths = authorityService.getContainedAuthorities(null, "GROUP_GrpD", true);
|
||
assertEquals(1, auths.size());
|
||
assertTrue(auths.toArray()[0].equals(tenantAdminName));
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test10CreateCategories()
|
||
{
|
||
logger.info("Create demo categories");
|
||
|
||
// super admin
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
logger.info("Create demo categories - super tenant");
|
||
createCategoriesImpl("");
|
||
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getAdminUserName());
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
logger.info("Create demo categories - "+tenantDomain);
|
||
|
||
createCategoriesImpl(tenantDomain);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
|
||
}
|
||
}
|
||
|
||
@SuppressWarnings("unchecked")
|
||
private void createCategoriesImpl(String tenantDomain)
|
||
{
|
||
if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
|
||
{
|
||
Collection<ChildAssociationRef> childAssocs = categoryService.getRootCategories(SPACES_STORE, ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||
|
||
for (ChildAssociationRef childAssoc : childAssocs)
|
||
{
|
||
if (nodeService.getProperty(childAssoc.getChildRef(), ContentModel.PROP_NAME).equals("CatA"))
|
||
{
|
||
return; // re-runnable, else we need to delete the created categories
|
||
}
|
||
}
|
||
}
|
||
|
||
// Find all root categories
|
||
String query = "PATH:\"/cm:generalclassifiable/*\"";
|
||
ResultSet resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||
int cnt = resultSet.length();
|
||
|
||
NodeRef catA = createCategory(SPACES_STORE, null, "CatA", "CatA-"+tenantDomain);
|
||
createCategory(SPACES_STORE, catA, "SubCatA", "SubCatA-"+tenantDomain); // ignore return
|
||
|
||
NodeRef catB = createCategory(SPACES_STORE, null, "CatB", "CatB-"+tenantDomain);
|
||
createCategory(SPACES_STORE, catB, "SubCatB", "SubCatB-"+tenantDomain); // ignore return
|
||
|
||
cnt = cnt + 2;
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
NodeRef catC = createCategory(SPACES_STORE, null, "CatC", "CatC-"+tenantDomain);
|
||
createCategory(SPACES_STORE, catC, "SubCatC", "SubCatC-"+tenantDomain); // ignore return
|
||
|
||
cnt = cnt + 1;
|
||
}
|
||
resultSet.close();
|
||
|
||
// Find all root categories
|
||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||
assertEquals(cnt, resultSet.length());
|
||
resultSet.close();
|
||
|
||
String queryMembers = "PATH:\"/cm:generalclassifiable//cm:catA/member\"";
|
||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, queryMembers);
|
||
assertEquals(0, resultSet.length());
|
||
resultSet.close();
|
||
|
||
NodeRef homeSpaceRef = getHomeSpaceFolderNode(AuthenticationUtil.getRunAsUser());
|
||
NodeRef contentRef = addContent(homeSpaceRef, "tqbfjotld.txt", "The quick brown fox jumps over the lazy dog (tenant " + tenantDomain + ")", MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
|
||
assertFalse(nodeService.hasAspect(contentRef, ContentModel.ASPECT_GEN_CLASSIFIABLE));
|
||
|
||
List<NodeRef> categories = (List<NodeRef>)nodeService.getProperty(contentRef, ContentModel.PROP_CATEGORIES);
|
||
assertNull(categories);
|
||
|
||
// Classify the node (ie. assign node to a particular category in a classification)
|
||
categories = new ArrayList<NodeRef>(1);
|
||
categories.add(catA);
|
||
|
||
HashMap<QName, Serializable> catProps = new HashMap<QName, Serializable>();
|
||
catProps.put(ContentModel.PROP_CATEGORIES, (Serializable)categories);
|
||
nodeService.addAspect(contentRef, ContentModel.ASPECT_GEN_CLASSIFIABLE, catProps);
|
||
|
||
assertTrue(nodeService.hasAspect(contentRef, ContentModel.ASPECT_GEN_CLASSIFIABLE));
|
||
|
||
categories = (List<NodeRef>)nodeService.getProperty(contentRef, ContentModel.PROP_CATEGORIES);
|
||
assertEquals(1, categories.size());
|
||
|
||
// test ETHREEOH-210
|
||
queryMembers = "PATH:\"/cm:generalclassifiable//cm:CatA/member\"";
|
||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, queryMembers);
|
||
assertEquals(1, resultSet.length());
|
||
resultSet.close();
|
||
}
|
||
|
||
public void test11CreateFolders()
|
||
{
|
||
logger.info("Create demo folders");
|
||
|
||
List<String> users = new ArrayList<String>(3);
|
||
users.add(TEST_USER1);
|
||
users.add(TEST_USER2);
|
||
users.add(TEST_USER3);
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
for (String baseUserName : users)
|
||
{
|
||
if ((! baseUserName.equals(TEST_USER3)) || (tenantDomain.equals(TEST_TENANT_DOMAIN2)))
|
||
{
|
||
final String tenantUserName = tenantService.getDomainUser(baseUserName, tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef homeSpaceRef = getHomeSpaceFolderNode(tenantUserName);
|
||
|
||
NodeRef folderRef = createFolderNode(homeSpaceRef, "myfolder1");
|
||
createFolderNode(folderRef, "mysubfolder1"); // ignore return
|
||
|
||
folderRef = createFolderNode(homeSpaceRef, "myfolder2");
|
||
createFolderNode(folderRef, "mysubfolder2"); // ignore return
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
folderRef = createFolderNode(homeSpaceRef, "myfolder3");
|
||
createFolderNode(folderRef, "mysubfolder3"); // ignore return
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, tenantUserName);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void test12CreateVersionableUserContent()
|
||
{
|
||
logger.info("Create demo content");
|
||
|
||
List<String> users = new ArrayList<String>(3);
|
||
users.add(TEST_USER1);
|
||
users.add(TEST_USER2);
|
||
users.add(TEST_USER3);
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
for (String baseUserName : users)
|
||
{
|
||
if ((! baseUserName.equals(TEST_USER3)) || (tenantDomain.equals(TEST_TENANT_DOMAIN2)))
|
||
{
|
||
final String tenantUserName = tenantService.getDomainUser(baseUserName, tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef homeSpaceRef = getHomeSpaceFolderNode(tenantUserName);
|
||
|
||
NodeRef contentRef = addContent(homeSpaceRef, tenantUserName+" quick brown fox.txt", "The quick brown fox jumps over the lazy dog (tenant " + tenantDomain + ")", MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
nodeService.addAspect(contentRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||
|
||
if (tenantDomain.equals(TEST_TENANT_DOMAIN2))
|
||
{
|
||
contentRef = addContent(homeSpaceRef, tenantUserName+" quick brown fox ANO.txt", "The quick brown fox jumps over the lazy dog ANO (tenant " + tenantDomain + ")", MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
nodeService.addAspect(contentRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}, tenantUserName);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void test13GetStores()
|
||
{
|
||
logger.info("Get tenant stores");
|
||
|
||
// system
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
for (StoreRef storeRef : nodeService.getStores())
|
||
{
|
||
System.out.println("StoreRef: "+storeRef);
|
||
}
|
||
|
||
assertTrue("System: "+nodeService.getStores().size()+", "+(tenants.size()+1), (nodeService.getStores().size() >= (DEFAULT_STORE_COUNT * (tenants.size()+1))));
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getSystemUserName());
|
||
|
||
// super admin
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
assertTrue("Super admin: "+nodeService.getStores().size(), (nodeService.getStores().size() >= DEFAULT_STORE_COUNT));
|
||
return null;
|
||
}
|
||
}, AuthenticationUtil.getAdminUserName());
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
Set<StoreRef> stores = new HashSet<StoreRef>(nodeService.getStores());
|
||
assertEquals("Tenant: "+tenantDomain, DEFAULT_STORES, stores);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test14GetProperty()
|
||
{
|
||
logger.info("Test get property");
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef personNodeRef = createUser(TEST_USER4, tenantDomain, TEST_USER4+" "+tenantDomain);
|
||
|
||
// Test nodeRef property
|
||
NodeRef homeFolderNodeRef = (NodeRef)nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||
assertFalse(homeFolderNodeRef.toString().contains(tenantDomain));
|
||
|
||
Map<QName, Serializable> props = (Map<QName, Serializable>)nodeService.getProperties(personNodeRef);
|
||
assertFalse(props.get(ContentModel.PROP_HOMEFOLDER).toString().contains(tenantDomain));
|
||
|
||
// Test "store-identifier" property
|
||
String storeId = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_STORE_IDENTIFIER);
|
||
assertFalse(storeId.contains(tenantDomain));
|
||
|
||
assertFalse(props.get(ContentModel.PROP_STORE_IDENTIFIER).toString().contains(tenantDomain));
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test15COCIandSearch()
|
||
{
|
||
logger.info("Test checkout/checkin and search");
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
// search for local copy of bootstrapped file 'invite_user_email.ftl' (see email_templates.acp)
|
||
String origText = "You have been invited to";
|
||
String query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/app:invite_email_templates/*\" +TEXT:\""+origText+"\"";
|
||
ResultSet resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||
assertEquals(1, resultSet.length());
|
||
|
||
NodeRef nodeRef = resultSet.getNodeRef(0);
|
||
resultSet.close();
|
||
|
||
// checkout, update and checkin
|
||
|
||
NodeRef workingCopyNodeRef = cociService.checkout(nodeRef);
|
||
|
||
ContentWriter writer = contentService.getWriter(workingCopyNodeRef, ContentModel.PROP_CONTENT, true);
|
||
|
||
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
writer.setEncoding("UTF-8");
|
||
|
||
String updateText = "Updated by "+tenantAdminName;
|
||
writer.putContent(updateText);
|
||
|
||
cociService.checkin(workingCopyNodeRef, null);
|
||
|
||
query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/app:invite_email_templates/*\" +TEXT:\""+origText+"\"";
|
||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||
assertEquals(0, resultSet.length());
|
||
resultSet.close();
|
||
|
||
query = "+PATH:\"/app:company_home/app:dictionary/app:email_templates/app:invite_email_templates/*\" +TEXT:\""+updateText+"\"";
|
||
resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query);
|
||
assertEquals(1, resultSet.length());
|
||
resultSet.close();
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test16DeleteArchiveAndRestoreContent()
|
||
{
|
||
logger.info("test delete/archive & restore content");
|
||
|
||
// note: CLOUD-1349 - ownership is based on fully authenticated user (else restoreNode fails for non-Admin user)
|
||
AuthenticationUtil.clearCurrentSecurityContext();
|
||
|
||
final String superAdmin = AuthenticationUtil.getAdminUserName();
|
||
|
||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||
{
|
||
public Void doWork() throws Exception
|
||
{
|
||
// super tenant - admin user
|
||
deleteArchiveAndRestoreContent(superAdmin, TenantService.DEFAULT_DOMAIN);
|
||
return null;
|
||
}
|
||
|
||
}, superAdmin);
|
||
|
||
final String superAnoUser = "superAnoUser";
|
||
|
||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||
{
|
||
public Void doWork() throws Exception
|
||
{
|
||
createUser(superAnoUser, TenantService.DEFAULT_DOMAIN, superAnoUser);
|
||
return null;
|
||
}
|
||
}, superAdmin);
|
||
|
||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||
{
|
||
public Void doWork() throws Exception
|
||
{
|
||
// super tenant - ano user
|
||
deleteArchiveAndRestoreContent(superAnoUser, TenantService.DEFAULT_DOMAIN);
|
||
|
||
return null;
|
||
}
|
||
}, superAnoUser);
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantUserName = tenantService.getDomainUser(TEST_USER1, tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
deleteArchiveAndRestoreContent(tenantUserName, tenantDomain);
|
||
|
||
return null;
|
||
}
|
||
}, tenantUserName);
|
||
}
|
||
}
|
||
|
||
private void deleteArchiveAndRestoreContent(String userName, String tenantDomain)
|
||
{
|
||
NodeRef homeSpaceRef = getHomeSpaceFolderNode(userName);
|
||
NodeRef contentRef = addContent(homeSpaceRef, userName+" "+System.currentTimeMillis()+" tqbfjotld.txt", "The quick brown fox jumps over the lazy dog (tenant " + tenantDomain + ")", MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
|
||
assertEquals(userName, ownableService.getOwner(contentRef));
|
||
permissionService.hasPermission(contentRef, PermissionService.DELETE_NODE);
|
||
|
||
NodeRef storeArchiveNode = nodeService.getStoreArchiveNode(contentRef.getStoreRef());
|
||
|
||
nodeService.deleteNode(contentRef);
|
||
|
||
// deduce archived nodeRef
|
||
StoreRef archiveStoreRef = storeArchiveNode.getStoreRef();
|
||
NodeRef archivedContentRef = new NodeRef(archiveStoreRef, contentRef.getId());
|
||
|
||
assertEquals(userName, ownableService.getOwner(archivedContentRef));
|
||
permissionService.hasPermission(archivedContentRef, PermissionService.DELETE_NODE);
|
||
|
||
//nodeService.restoreNode(archivedContentRef, null, null, null);
|
||
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(archivedContentRef);
|
||
assertNotNull(report);
|
||
|
||
NodeRef restoredNodeRef = report.getRestoredNodeRef();
|
||
assertNotNull(restoredNodeRef);
|
||
|
||
archivedContentRef = new NodeRef(archiveStoreRef, restoredNodeRef.getId());
|
||
|
||
nodeService.deleteNode(restoredNodeRef);
|
||
|
||
nodeArchiveService.purgeArchivedNode(archivedContentRef);
|
||
}
|
||
|
||
public void test17CustomModels()
|
||
{
|
||
logger.info("test custom models");
|
||
|
||
final int defaultModelCnt = dictionaryService.getAllModels().size();
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
// no custom models should be deployed yet (note: will fail if re-run)
|
||
assertEquals(0, repoAdminService.getModels().size());
|
||
assertEquals(defaultModelCnt, dictionaryService.getAllModels().size());
|
||
assertNull(dictionaryService.getClass(QName.createQName("{my.new.model}sop")));
|
||
|
||
// deploy custom model
|
||
InputStream modelStream = getClass().getClassLoader().getResourceAsStream("tenant/exampleModel.xml");
|
||
repoAdminService.deployModel(modelStream, "exampleModel.xml");
|
||
|
||
assertEquals(1, repoAdminService.getModels().size());
|
||
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
|
||
|
||
ClassDefinition myType = dictionaryService.getClass(QName.createQName("{my.new.model}sop"));
|
||
assertNotNull(myType);
|
||
assertEquals(QName.createQName("{my.new.model}mynewmodel"),myType.getModel().getName());
|
||
|
||
// deactivate model
|
||
repoAdminService.deactivateModel("exampleModel.xml");
|
||
|
||
assertEquals(1, repoAdminService.getModels().size()); // still deployed, although not active
|
||
assertEquals(defaultModelCnt, dictionaryService.getAllModels().size());
|
||
assertNull(dictionaryService.getClass(QName.createQName("{my.new.model}sop")));
|
||
|
||
// re-activate model
|
||
repoAdminService.activateModel("exampleModel.xml");
|
||
|
||
assertEquals(1, repoAdminService.getModels().size());
|
||
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
|
||
|
||
myType = dictionaryService.getClass(QName.createQName("{my.new.model}sop"));
|
||
assertNotNull(myType);
|
||
assertEquals(QName.createQName("{my.new.model}mynewmodel"),myType.getModel().getName());
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test18AddCustomWebClient()
|
||
{
|
||
// note: add as demo files - need to re-start Alfresco to see custom web client config / messages
|
||
logger.info("test add custom web client config");
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef webClientExtFolder = getWebClientExtensionNodeRef(SPACES_STORE);
|
||
|
||
InputStream is = getClass().getClassLoader().getResourceAsStream("tenant/webclient.properties");
|
||
addContent(webClientExtFolder, "webclient.properties", is, MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
|
||
is = getClass().getClassLoader().getResourceAsStream("tenant/web-client-config-custom.xml");
|
||
addContent(webClientExtFolder, "web-client-config-custom.xml", is, MimetypeMap.MIMETYPE_XML);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
}
|
||
|
||
public void test19FileFolder()
|
||
{
|
||
logger.info("test file/folder list");
|
||
|
||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||
|
||
for (final String tenantDomain : tenants)
|
||
{
|
||
final String tenantUserName = tenantService.getDomainUser(TEST_USER1, tenantDomain);
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
List<String> pathElements = new ArrayList<String>(2);
|
||
pathElements.add("Data Dictionary");
|
||
pathElements.add("Presentation Templates");
|
||
|
||
NodeRef chRef = repositoryHelper.getCompanyHome();
|
||
NodeRef ddRef = fileFolderService.resolveNamePath(chRef, pathElements).getNodeRef();
|
||
|
||
assertTrue(fileFolderService.list(ddRef).size() > 0);
|
||
|
||
return null;
|
||
}
|
||
}, tenantUserName);
|
||
}
|
||
}
|
||
|
||
|
||
// TODO pending CLOUD-1350 fix
|
||
public void xtest20_ALF_12732()
|
||
{
|
||
final String tenantDomain1 = TEST_RUN+".one.alf12732";
|
||
|
||
createTenant(tenantDomain1);
|
||
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain1);
|
||
|
||
try
|
||
{
|
||
AuthenticationUtil.setFullyAuthenticatedUser(tenantAdminName); // note: since SiteServiceImpl.setupSitePermissions currently uses getCurrentUserName (rather than runAs)
|
||
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
createSite("site1");
|
||
|
||
NodeRef docLib1Ref = siteService.getContainer("site1", SiteService.DOCUMENT_LIBRARY);
|
||
NodeRef contentRef = addContent(docLib1Ref, "tqbfjotld.txt", "The quick brown fox jumps over the lazy dog", MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||
|
||
createSite("site2");
|
||
|
||
NodeRef docLib2Ref = siteService.getContainer("site2", SiteService.DOCUMENT_LIBRARY);
|
||
|
||
nodeService.moveNode(contentRef, docLib2Ref, ContentModel.ASSOC_CONTAINS, QName.createQName("tqbfjotld.txt"));
|
||
|
||
// for Share, called via "move-to.post.json.js" -> ScriptSiteService.cleanSitePermissions
|
||
siteService.cleanSitePermissions(contentRef, null);
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
finally
|
||
{
|
||
AuthenticationUtil.clearCurrentSecurityContext();
|
||
}
|
||
}
|
||
|
||
public void test21_ALF_14354()
|
||
{
|
||
final String tenantDomain1 = TEST_RUN+".one.alf14354";
|
||
final String tenantDomain2 = TEST_RUN+".two.alf14354";
|
||
|
||
createTenant(tenantDomain1);
|
||
createTenant(tenantDomain2);
|
||
|
||
String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain1);
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef rootNodeRef = repositoryHelper.getRootHome();
|
||
|
||
assertTrue(nodeService.exists(rootNodeRef));
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
|
||
tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain2);
|
||
TenantUtil.runAsPrimaryTenant(new TenantRunAsWork<Object>()
|
||
{
|
||
public Object doWork() throws Exception
|
||
{
|
||
NodeRef rootNodeRef = repositoryHelper.getRootHome();
|
||
|
||
assertTrue(nodeService.exists(rootNodeRef));
|
||
|
||
return null;
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
|
||
|
||
private int searchForDataDictionary(String tenantAdminName, final String query)
|
||
{
|
||
return AuthenticationUtil.runAs(new RunAsWork<Integer>()
|
||
{
|
||
public Integer doWork() throws Exception
|
||
{
|
||
ResultSet resultSet = searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query, null);
|
||
return resultSet.length();
|
||
}
|
||
}, tenantAdminName);
|
||
}
|
||
|
||
// pseudo cleanup - if this test runs last
|
||
public void test22DeleteAllTenants()
|
||
{
|
||
logger.info("test delete tenants");
|
||
|
||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||
|
||
List<Tenant> allTenants = tenantAdminService.getAllTenants();
|
||
for (final Tenant tenant : allTenants)
|
||
{
|
||
deleteTenant(tenant.getTenantDomain());
|
||
}
|
||
}
|
||
|
||
/*
|
||
public static void main(String args[])
|
||
{
|
||
System.out.println(new Date());
|
||
junit.textui.TestRunner.run(MultiTDemoTest.class);
|
||
System.out.println(new Date());
|
||
}
|
||
*/
|
||
}
|