>From 30f2932b773aa6cea186a41268afd5ba1934cd34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 24 Jul 2015 09:55:28 +0200
Subject: [PATCH 2/4] SYSDB: prepare for LOCAL view

Objects doesn't have to have overrideDN specified when using LOCAL view.
Since the view is not stored on the server we do not want to contact
LDAP therefore we special case LOCAL view saying that it is OK that
this attribute is missing.

Preparation for:
https://fedorahosted.org/sssd/ticket/2584
---
 src/db/sysdb.h                      | 14 +++++++-
 src/db/sysdb_views.c                |  7 ++++
 src/providers/ipa/ipa_subdomains.c  |  3 +-
 src/tests/cmocka/test_sysdb_views.c | 66 +++++++++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 0f745ccb1a646d77ba4ad3d714d5f4dce0a51211..9e28b5c6691f3710e3051d9746ac5fa47aff8424 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -157,9 +157,10 @@
 #define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires"
 #define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl"
 
+#define SYSDB_DEFAULT_VIEW_NAME "default"
+#define SYSDB_LOCAL_VIEW_NAME "LOCAL" /* reserved for client-side overrides */
 #define SYSDB_VIEW_CLASS "view"
 #define SYSDB_VIEW_NAME "viewName"
-#define SYSDB_DEFAULT_VIEW_NAME "default"
 #define SYSDB_OVERRIDE_CLASS "overrride"
 #define SYSDB_OVERRIDE_ANCHOR_UUID "overrideAnchorUUID"
 #define SYSDB_OVERRIDE_USER_CLASS "userOverride"
@@ -473,6 +474,17 @@ static inline bool is_default_view(const char *view_name)
     }
 }
 
+static inline bool is_local_view(const char *view_name)
+{
+    /* NULL is treated as default */
+    if (view_name != NULL
+            && strcmp(view_name, SYSDB_LOCAL_VIEW_NAME) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
 errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
 
 errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb);
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index aadd6018f4d1e2ca33e2e00dd8b13b55a8c03f3e..1db6c892de9e4764b673608166830800744b1148 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -1186,9 +1186,16 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
         override_dn_str = ldb_msg_find_attr_as_string(obj,
                                                       SYSDB_OVERRIDE_DN, NULL);
         if (override_dn_str == NULL) {
+            if (is_local_view(domain->view_name)) {
+                /* LOCAL view doesn't have to have overrideDN specified. */
+                ret = EOK;
+                goto done;
+            }
+
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Missing override DN for objext [%s].\n",
                   ldb_dn_get_linearized(obj->dn));
+
             ret = ENOENT;
             goto done;
         }
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index cf72784473747c67d44a5d887faf867cfe62ce2b..cec8b3918b8f832e2c7376a867448fe876da6ffc 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -905,7 +905,8 @@ static void ipa_get_view_name_done(struct tevent_req *req)
                     goto done;
                 }
 
-                if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)) {
+                if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)
+                        && !is_local_view(ctx->sd_ctx->id_ctx->view_name)) {
                     /* Old view was not the default view, delete view tree */
                     ret = sysdb_delete_view_tree(
                                              ctx->sd_ctx->be_ctx->domain->sysdb,
diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
index 123d4c5cb613f41e1bca9e89feed701a1e86f8d3..83007b76a625edef67109850648b2d71645e22bb 100644
--- a/src/tests/cmocka/test_sysdb_views.c
+++ b/src/tests/cmocka/test_sysdb_views.c
@@ -281,6 +281,68 @@ void test_sysdb_add_overrides_to_object(void **state)
     assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0);
 }
 
+void test_sysdb_add_overrides_to_object_local(void **state)
+{
+    int ret;
+    struct ldb_message *orig;
+    struct ldb_message_element *el;
+    char *tmp_str;
+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                         struct sysdb_test_ctx);
+
+    orig = ldb_msg_new(test_ctx);
+    assert_non_null(orig);
+
+    tmp_str = talloc_strdup(orig,  "ORIGNAME");
+    assert_non_null(tmp_str);
+    ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
+    assert_int_equal(ret, EOK);
+
+    tmp_str = talloc_strdup(orig,  "ORIGGECOS");
+    assert_non_null(tmp_str);
+    ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
+    assert_int_equal(ret, EOK);
+
+    test_ctx->domain->has_views = true;
+    test_ctx->domain->view_name = "LOCAL";
+
+    ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL);
+    assert_int_equal(ret, EOK);
+}
+
+void test_sysdb_add_overrides_to_object_missing_overridedn(void **state)
+{
+    int ret;
+    struct ldb_message *orig;
+    struct ldb_message_element *el;
+    char *tmp_str;
+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                         struct sysdb_test_ctx);
+
+    orig = ldb_msg_new(test_ctx);
+    assert_non_null(orig);
+
+    orig->dn = ldb_dn_new(orig, test_ctx->domain->sysdb->ldb,
+                          "cn=somedn,dc=example,dc=com");
+    assert_non_null(orig->dn);
+
+    tmp_str = talloc_strdup(orig,  "ORIGNAME");
+    assert_non_null(tmp_str);
+    ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
+    assert_int_equal(ret, EOK);
+
+    tmp_str = talloc_strdup(orig,  "ORIGGECOS");
+    assert_non_null(tmp_str);
+    ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
+    assert_int_equal(ret, EOK);
+
+    test_ctx->domain->has_views = true;
+    test_ctx->domain->view_name = "NON-LOCAL";
+
+    ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL);
+    assert_int_equal(ret, ENOENT);
+}
+
 void test_split_ipa_anchor(void **state)
 {
     int ret;
@@ -923,6 +985,10 @@ int main(int argc, const char *argv[])
                                         test_sysdb_setup, test_sysdb_teardown),
         cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object,
                                         test_sysdb_setup, test_sysdb_teardown),
+        cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_local,
+                                        test_sysdb_setup, test_sysdb_teardown),
+        cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_missing_overridedn,
+                                        test_sysdb_setup, test_sysdb_teardown),
         cmocka_unit_test_setup_teardown(test_split_ipa_anchor,
                                         test_sysdb_setup, test_sysdb_teardown),
         cmocka_unit_test_setup_teardown(test_sysdb_delete_view_tree,
-- 
1.9.3

