/**
  *  \file u/t_server_talk_accesschecker.cpp
  *  \brief Test for server::talk::AccessChecker
  */

#include <stdexcept>
#include "server/talk/accesschecker.hpp"

#include "t_server_talk.hpp"
#include "server/talk/forum.hpp"
#include "server/talk/topic.hpp"
#include "server/talk/root.hpp"
#include "server/talk/session.hpp"
#include "afl/net/redis/internaldatabase.hpp"
#include "afl/net/nullcommandhandler.hpp"
#include "server/talk/message.hpp"

void
TestServerTalkAccessChecker::testIt()
{
    // Infrastructure
    afl::net::redis::InternalDatabase db;
    afl::net::NullCommandHandler mq;
    server::talk::Root root(db, mq, server::talk::Configuration());

    // Database content
    // - forum 1: readable by user 1001
    server::talk::Forum f1(root, 1);
    f1.readPermissions().set("u:1001");
    root.allForums().add(1);

    // - topic 11: readable by user 1002
    server::talk::Topic t11(root, 11);
    t11.readPermissions().set("u:1002");
    t11.forumId().set(1);
    f1.topics().add(11);

    // - topic 12: no permissions set
    server::talk::Topic t12(root, 12);
    t12.forumId().set(1);
    f1.topics().add(12);

    // - message 21: in topic 11
    server::talk::Message m21(root, 21);
    m21.topicId().set(11);
    t11.messages().add(21);
    f1.messages().add(21);

    // - message 22: in topic 11
    server::talk::Message m22(root, 22);
    m22.topicId().set(12);
    t12.messages().add(22);
    f1.messages().add(22);

    // Check root access
    {
        server::talk::Session s;
        server::talk::AccessChecker testee(root, s);
        TS_ASSERT(testee.isAllowed(t11));
        TS_ASSERT(testee.isAllowed(m21));
        TS_ASSERT(testee.isAllowed(m22));
        TS_ASSERT(testee.isAllowed(t12));
    }

    // Check user 1001 access: can read the second topic
    {
        server::talk::Session s;
        s.setUser("1001");
        server::talk::AccessChecker testee(root, s);
        TS_ASSERT(!testee.isAllowed(t11));
        TS_ASSERT(!testee.isAllowed(m21));
        TS_ASSERT(testee.isAllowed(m22));
        TS_ASSERT(testee.isAllowed(t12));
    }
    
    // Check user 1002 access: can read the second topic
    {
        server::talk::Session s;
        s.setUser("1002");
        server::talk::AccessChecker testee(root, s);
        TS_ASSERT(testee.isAllowed(t11));
        TS_ASSERT(testee.isAllowed(m21));
        TS_ASSERT(!testee.isAllowed(m22));
        TS_ASSERT(!testee.isAllowed(t12));
    }
    
    // Check user 1003 access: cannot read anything
    {
        server::talk::Session s;
        s.setUser("1003");
        server::talk::AccessChecker testee(root, s);
        TS_ASSERT(!testee.isAllowed(t11));
        TS_ASSERT(!testee.isAllowed(m21));
        TS_ASSERT(!testee.isAllowed(m22));
        TS_ASSERT(!testee.isAllowed(t12));

        TS_ASSERT_THROWS(testee.checkMessage(m21), std::exception);
        TS_ASSERT_THROWS(testee.checkTopic(t11), std::exception);
    }
}

