Log warning if adaptor user is having other than full read permission on
SharePoint content.
b/10034461
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
index 8623707..f692a68 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
@@ -208,27 +208,21 @@
    */
   private static final Pattern ALTERNATIVE_VALUE_PATTERN
       = Pattern.compile("^\\d+;#");
-  /**
-   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
-   */
-  private static final long VIEW_LIST_ITEMS_MASK = 0x0000000000000001;
-  /**
-   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
-   */
-  private static final long OPEN_MASK = 0x0000000000010000;
-  /**
-   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
-   */
-  private static final long VIEW_PAGES_MASK = 0x0000000000020000;
-  /**
-   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
-   */
-  private static final long MANAGE_LIST_MASK = 0x0000000000000800;
 
-  static final long LIST_ITEM_MASK
-      = OPEN_MASK | VIEW_PAGES_MASK | VIEW_LIST_ITEMS_MASK;
+  static final long LIST_ITEM_MASK = SPBasePermissions.OPEN 
+      | SPBasePermissions.VIEWPAGES | SPBasePermissions.VIEWLISTITEMS;
+
   private static final long READ_SECURITY_LIST_ITEM_MASK
-      = OPEN_MASK | VIEW_PAGES_MASK | VIEW_LIST_ITEMS_MASK | MANAGE_LIST_MASK;
+      = SPBasePermissions.OPEN | SPBasePermissions.VIEWPAGES 
+      | SPBasePermissions.VIEWLISTITEMS | SPBasePermissions.MANAGELISTS;
+  
+  private static final long FULL_READ_PERMISSION_MASK = SPBasePermissions.OPEN
+      | SPBasePermissions.VIEWLISTITEMS | SPBasePermissions.OPENITEMS
+      | SPBasePermissions.VIEWVERSIONS | SPBasePermissions.VIEWPAGES
+      | SPBasePermissions.VIEWUSAGEDATA | SPBasePermissions.BROWSEDIRECTORIES
+      | SPBasePermissions.VIEWFORMPAGES | SPBasePermissions.ENUMERATEPERMISSIONS
+      | SPBasePermissions.BROWSEUSERINFO | SPBasePermissions.USEREMOTEAPIS
+      | SPBasePermissions.USECLIENTINTEGRATION;
 
   private static final int LIST_READ_SECURITY_ENABLED = 2;
 
@@ -593,6 +587,10 @@
 
       // Test out configuration.
       VirtualServer vs = virtualServerSiteDataClient.getContentVirtualServer();
+
+      // Check Full Read permission for Adaptor User on SharePoint
+      checkFullReadPermissionForAdaptorUser(vs, username);
+
       String version = vs.getMetadata().getVersion();
       log.log(Level.INFO, "SharePoint Version : {0}", version);
       // Version is missing for SP 2007 (but its version is 12).
@@ -663,6 +661,81 @@
     Authenticator.setDefault(null);
     ntlmAuthenticator = null;
   }
+  /**
+   * Method to check full read permission for adaptor user on SharePoint.
+   * Returns -1 if adaptor user is not available in web application policy.
+   * Returns 0 if adaptor user is having other than Full Read permission
+   * Returns 1 if adaptor user is having exact Full Read permission.
+   */
+  @VisibleForTesting  
+  static int checkFullReadPermissionForAdaptorUser(VirtualServer vs,
+      String username) {
+    String adaptorUser = getAdaptorUser(username);
+    if (adaptorUser == null) {
+      log.log(Level.WARNING, "Unable to get adaptor user name");
+      return -1;
+    }
+    PolicyUser p = getPolicyUserForAdatorUser(vs, adaptorUser);
+    if (p == null) {
+      log.log(Level.INFO, "Adaptor user [{0}] not available in web "
+          + "application policy to verify permissions.", adaptorUser);
+      return -1;
+    }
+    if (isOtherThanFullReadForPolicyUser( p.getGrantMask().longValue())) {
+      log.log(Level.WARNING, "Adaptor user [{0}] is not having exact full "
+          + "read permission on SharePoint. Having excess or lesser "
+          + "permissions on SharePoint for adaptor user might affect adaptor "
+          + "functionality.", adaptorUser);
+      return 0;      
+    } else {
+      log.log(Level.FINE, "Adaptor user [{0}] is having full read "
+          + "permissions on SharePoint.", adaptorUser);
+      return 1;
+    }
+  }
+
+  private static PolicyUser getPolicyUserForAdatorUser(VirtualServer vs,
+      String adaptorUser) {
+    if (adaptorUser == null) {
+      return null;
+    }
+    for(PolicyUser p : vs.getPolicies().getPolicyUser()) {
+      String policyUser = decodeClaim(
+          p.getLoginName(), p.getLoginName(), false);
+      if (policyUser == null) {
+        // Un-supported claim type
+        continue;
+      }
+      // parse out authentication provider for forms authenticated user
+      policyUser = policyUser.substring(policyUser.indexOf(":") + 1);
+      if (adaptorUser.equalsIgnoreCase(policyUser)) {
+        return p;
+      }
+    }
+    return null;
+  }
+
+  private static boolean isOtherThanFullReadForPolicyUser(long permissionMask) {
+    return (FULL_READ_PERMISSION_MASK != permissionMask);
+  }
+
+  @VisibleForTesting
+  static String getAdaptorUser(String username) {
+    if (!"".equals(username)) {
+      return username;
+    }
+
+    // USERNAME and USERDOMAIN environment variables are applicable for 
+    // Windows only. On non windows adaptor machine user name will 
+    // not be empty.
+    // Using Ssytem.getenv instead on System.getProperty("user.name") because
+    // System.getProperty("user.name") returns username without domain.
+    if (System.getenv("USERDOMAIN") == null 
+        || System.getenv("USERNAME") == null) {
+      return null;
+    }
+    return  System.getenv("USERDOMAIN") + "\\" + System.getenv("USERNAME");
+  }
 
   private synchronized void shutdownExecutor(ExecutorService executor) {
     if (executor == null) {
@@ -1173,6 +1246,49 @@
   }
 
   @VisibleForTesting
+  static String decodeClaim(String loginName, String name
+      , boolean isDomainGroup) {
+    if (!loginName.startsWith(IDENTITY_CLAIMS_PREFIX)
+        && !loginName.startsWith(OTHER_CLAIMS_PREFIX)) {
+      return loginName;
+    }
+    // AD User
+    if (loginName.startsWith("i:0#.w|")) {
+      return loginName.substring(7);
+    // AD Group
+    } else if (loginName.startsWith("c:0+.w|")) {
+      return name;
+    } else if (loginName.equals("c:0(.s|true")) {
+      return "Everyone";
+    } else if (loginName.equals("c:0!.s|windows")) {
+      return "NT AUTHORITY\\authenticated users";
+    // Forms authentication role  
+    } else if (loginName.startsWith("c:0-.f|")) {
+      return loginName.substring(7).replace("|", ":");
+    // Forms authentication user  
+    } else if (loginName.startsWith("i:0#.f|")) {
+      return loginName.substring(7).replace("|", ":");
+    // Identity claims for Email (05) or UPN (0e) for trusted user claim
+    } else if (loginName.startsWith("i:05.t|") 
+        || loginName.startsWith("i:0e.t|")) {
+      String[] parts = loginName.split(Pattern.quote("|"), 3);
+      if (parts.length == 3) {
+        return parts[2];
+      }
+    // Non identity claims for email (05) or UPN (0e) or Role (0-)
+    } else if (loginName.startsWith("c:05.t|") 
+        || loginName.startsWith("c:0e.t|") 
+        || loginName.startsWith("c:0-.t|")) {
+      String[] parts = loginName.split(Pattern.quote("|"), 3);
+      if (parts.length == 3) {
+        return parts[2];
+      }
+    }
+    log.log(Level.WARNING, "Unsupported claims value {0}", loginName);
+    return null;
+  }
+
+  @VisibleForTesting
   class SiteAdaptor {
     private final SiteDataClient siteDataClient;
     private final UserGroupSoap userGroup;
@@ -1865,7 +1981,7 @@
     }
 
     private boolean isAllowAnonymousPeekForWeb(CachedWeb w) {
-      return isPermitted(w.anonymousPermMask, OPEN_MASK);
+      return isPermitted(w.anonymousPermMask, SPBasePermissions.OPEN);
     }
 
     private boolean isAllowAnonymousReadForWeb(CachedWeb w) {
@@ -1881,7 +1997,7 @@
           = (l.readSecurity != LIST_READ_SECURITY_ENABLED)
           && (l.allowAnonymousAccess == TrueFalseType.TRUE)
           && (l.anonymousViewListItems == TrueFalseType.TRUE)
-          && isPermitted(l.anonymousPermMask, VIEW_LIST_ITEMS_MASK);
+          && isPermitted(l.anonymousPermMask, SPBasePermissions.VIEWLISTITEMS);
       return allowAnonymousRead;
     }
 
@@ -2396,48 +2512,6 @@
       return true;
     }
 
-    private String decodeClaim(String loginName, String name
-        , boolean isDomainGroup) {
-      if (!loginName.startsWith(IDENTITY_CLAIMS_PREFIX)
-          && !loginName.startsWith(OTHER_CLAIMS_PREFIX)) {
-        return loginName;
-      }
-      // AD User
-      if (loginName.startsWith("i:0#.w|")) {
-        return loginName.substring(7);
-      // AD Group
-      } else if (loginName.startsWith("c:0+.w|")) {
-        return name;
-      } else if (loginName.equals("c:0(.s|true")) {
-        return "Everyone";
-      } else if (loginName.equals("c:0!.s|windows")) {
-        return "NT AUTHORITY\\authenticated users";
-      // Forms authentication role  
-      } else if (loginName.startsWith("c:0-.f|")) {
-        return loginName.substring(7).replace("|", ":");
-      // Forms authentication user  
-      } else if (loginName.startsWith("i:0#.f|")) {
-        return loginName.substring(7).replace("|", ":");
-      // Identity claims for Email (05) or UPN (0e) for trusted user claim
-      } else if (loginName.startsWith("i:05.t|") 
-          || loginName.startsWith("i:0e.t|")) {
-        String[] parts = loginName.split(Pattern.quote("|"), 3);
-        if (parts.length == 3) {
-          return parts[2];
-        }
-      // Non identity claims for email (05) or UPN (0e) or Role (0-)
-      } else if (loginName.startsWith("c:05.t|") 
-          || loginName.startsWith("c:0e.t|") 
-          || loginName.startsWith("c:0-.t|")) {
-        String[] parts = loginName.split(Pattern.quote("|"), 3);
-        if (parts.length == 3) {
-          return parts[2];
-        }
-      }
-      log.log(Level.WARNING, "Unsupported claims value {0}", loginName);
-      return null;
-    }
-
     private Map<String, PrincipalInfo> resolvePrincipals(
         List<String> principalsToResolve) {
       Map<String, PrincipalInfo> resolved
@@ -2894,6 +2968,47 @@
     }
   }
 
+  /**
+   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
+   */
+  private static class SPBasePermissions {
+    public static final long EMPTYMASK= 0x0000000000000000;
+    public static final long VIEWLISTITEMS= 0x0000000000000001;
+    public static final long ADDLISTITEMS= 0x0000000000000002;
+    public static final long EDITLISTITEMS= 0x0000000000000004;
+    public static final long DELETELISTITEMS= 0x0000000000000008;
+    public static final long APPROVEITEMS= 0x0000000000000010;
+    public static final long OPENITEMS= 0x0000000000000020;
+    public static final long VIEWVERSIONS= 0x0000000000000040;
+    public static final long DELETEVERSIONS= 0x0000000000000080;
+    public static final long CANCELCHECKOUT= 0x0000000000000100;
+    public static final long MANAGEPERSONALVIEWS= 0x0000000000000200;
+    public static final long MANAGELISTS= 0x0000000000000800;
+    public static final long VIEWFORMPAGES= 0x0000000000001000;
+    public static final long OPEN= 0x0000000000010000;
+    public static final long VIEWPAGES= 0x0000000000020000;
+    public static final long ADDANDCUSTOMIZEPAGES= 0x0000000000040000;
+    public static final long APPLYTHEMEANDBORDER= 0x0000000000080000;
+    public static final long APPLYSTYLESHEETS= 0x0000000000100000;
+    public static final long VIEWUSAGEDATA= 0x0000000000200000;
+    public static final long CREATESSCSITE= 0x0000000000400000;
+    public static final long MANAGESUBWEBS= 0x0000000000800000;
+    public static final long CREATEGROUPS= 0x0000000001000000;
+    public static final long MANAGEPERMISSIONS= 0x0000000002000000;
+    public static final long BROWSEDIRECTORIES= 0x0000000004000000;
+    public static final long BROWSEUSERINFO= 0x0000000008000000;
+    public static final long ADDDELPRIVATEWEBPARTS= 0x0000000010000000;
+    public static final long UPDATEPERSONALWEBPARTS= 0x0000000020000000;
+    public static final long MANAGEWEB= 0x0000000040000000;
+    public static final long USECLIENTINTEGRATION= 0x0000001000000000L;
+    public static final long USEREMOTEAPIS= 0x0000002000000000L;
+    public static final long MANAGEALERTS= 0x0000004000000000L;
+    public static final long CREATEALERTS= 0x0000008000000000L;
+    public static final long EDITMYUSERINFO= 0x0000010000000000L;
+    public static final long ENUMERATEPERMISSIONS= 0x4000000000000000L;
+    public static final long FULLMASK= 0x7FFFFFFFFFFFFFFFL;
+  }
+
   private class MemberIdMappingCallable implements Callable<MemberIdMapping> {
     private final String siteUrl;
 
diff --git a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
index 1d260d5..9ce1fb3 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
@@ -44,6 +44,7 @@
 import com.microsoft.schemas.sharepoint.soap.ObjectType;
 import com.microsoft.schemas.sharepoint.soap.SPContentDatabase;
 import com.microsoft.schemas.sharepoint.soap.SiteDataSoap;
+import com.microsoft.schemas.sharepoint.soap.VirtualServer;
 import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationMode;
 import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
 import com.microsoft.schemas.sharepoint.soap.authentication.LoginResult;
@@ -423,6 +424,21 @@
   }
   
   @Test
+  public void testCheckFullReadPermissionForAdaptorUser() throws Exception {
+    MockSiteData siteDataSoap = new MockSiteData()
+        .register(VS_CONTENT_EXCHANGE).register(CD_CONTENT_EXCHANGE);
+    VirtualServer vs = new SiteDataClient(siteDataSoap, true)
+        .getContentVirtualServer();
+
+    assertEquals(1, SharePointAdaptor.checkFullReadPermissionForAdaptorUser(vs,
+        "GDC-PSL\\spuser1"));
+    assertEquals(0, SharePointAdaptor.checkFullReadPermissionForAdaptorUser(vs,
+        "GDC-PSL\\administrator"));
+    assertEquals(-1, SharePointAdaptor.checkFullReadPermissionForAdaptorUser(vs,
+        "Some Fake User"));
+  }
+
+  @Test
   public void testAdaptorInitAdfsUnknownHostException() throws Exception {
     SoapFactory siteDataFactory = MockSoapFactory.blank()
         .endpoint(VS_ENDPOINT, MockSiteData.blank()