Skip to content
This repository has been archived by the owner on Feb 13, 2020. It is now read-only.

Commit

Permalink
Adds a command line tool for migrating wiki principals into resource …
Browse files Browse the repository at this point in the history
…principals in case you no longer want to be coupled to a wiki server.
  • Loading branch information
m0rgen committed Mar 4, 2017
1 parent cd569ec commit 21dc757
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 3 deletions.
62 changes: 62 additions & 0 deletions calendarserver/tools/test/test_wiki.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
##
# Copyright (c) 2005-2017 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##


from twisted.internet.defer import inlineCallbacks
from calendarserver.tools.wiki import migrateWiki
from twistedcaldav.test.util import StoreTestCase
from txdav.who.wiki import DirectoryService as WikiDirectoryService
from txdav.who.idirectory import RecordType as CalRecordType


class MigrateWikiTest(StoreTestCase):

def configure(self):
super(MigrateWikiTest, self).configure()
self.patch(self.config.Authentication.Wiki, "Enabled", False)

@inlineCallbacks
def test_migrateWiki(self):

# Ensure the two records do not exist yet
record = yield self.directory.recordWithUID(u"wiki-xyzzy")
self.assertEquals(record, None)
record = yield self.directory.recordWithUID(u"wiki-plugh")
self.assertEquals(record, None)

# We need to create the calendar homes, but we can't unless there are
# records for these uids. Since we've disabled the wiki service above,
# we're temporarily going to substitute a wiki directory service while
# we create the calendar homes:
realDirectory = self.store.directoryService()
tmpWikiService = WikiDirectoryService("test", None)
tmpWikiService.serversDB = lambda : None
self.store._directoryService = tmpWikiService
txn = self.store.newTransaction()
yield txn.calendarHomeWithUID(u"wiki-xyzzy", create=True)
yield txn.calendarHomeWithUID(u"wiki-plugh", create=True)
yield txn.commit()
self.store._directoryService = realDirectory

# Migrate wiki principals to resources
yield migrateWiki(self.store)

record = yield self.directory.recordWithUID(u"wiki-xyzzy")
self.assertEquals(record.shortNames, [u"xyzzy"])
self.assertEquals(record.recordType, CalRecordType.resource)
record = yield self.directory.recordWithUID(u"wiki-plugh")
self.assertEquals(record.shortNames, [u"plugh"])
self.assertEquals(record.recordType, CalRecordType.resource)
139 changes: 139 additions & 0 deletions calendarserver/tools/wiki.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env python

##
# Copyright (c) 2006-2017 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##

from __future__ import print_function

__all__ = [
"migrateWiki",
]

from getopt import getopt, GetoptError
import os
import sys

from calendarserver.tools.cmdline import utilityMain, WorkerService
from twext.enterprise.dal.syntax import Select
from twext.python.log import Logger
from twext.who.directory import DirectoryRecord
from twisted.internet.defer import inlineCallbacks
from txdav.common.datastore.sql_tables import schema
from txdav.who.idirectory import RecordType as CalRecordType
from txdav.who.wiki import DirectoryService as WikiDirectoryService

log = Logger()


class WikiMigrationService(WorkerService):

@inlineCallbacks
def doWork(self):
yield migrateWiki(self.store)


def usage():

name = os.path.basename(sys.argv[0])
print("usage: %s [options] " % (name,))
print("")
print(" Migrates Wiki principals into Calendar Server resources")
print("")
print("options:")
print(" -h --help: print this help and exit")
print(" -f --config <path>: Specify caldavd.plist configuration path")
print("")

sys.exit(0)


def main():
try:
(optargs, _ignore_args) = getopt(
sys.argv[1:], "hf:", [
"help",
"config=",
],
)
except GetoptError, e:
usage(e)

#
# Get configuration
#
configFileName = None

for opt, arg in optargs:
if opt in ("-h", "--help"):
usage()

elif opt in ("-f", "--config"):
configFileName = arg

else:
raise NotImplementedError(opt)

def _patchConfig(config):
# Disable Wiki DirectoryService so when we look up uids we don't get
# the synthesized ones.
config.Authentication.Wiki.Enabled = False

utilityMain(configFileName, WikiMigrationService, patchConfig=_patchConfig)


@inlineCallbacks
def migrateWiki(store):
"""
Iterate calendar homes looking for wiki principals; create resources
for each.
"""

directory = store.directoryService()
recordType = CalRecordType.resource
prefix = WikiDirectoryService.uidPrefix
ch = schema.CALENDAR_HOME

# Look up in the DB all the uids starting with the wiki prefix
txn = store.newTransaction()
rows = (yield Select(
[ch.OWNER_UID, ],
From=ch,
Where=(ch.OWNER_UID.StartsWith(prefix)),
).on(txn))
yield txn.commit()

# For each wiki uid, if the resource record does not already exist,
# create a record
for uid in [row[0] for row in rows]:
uid = uid.decode("utf-8")
record = yield directory.recordWithUID(uid)
if record is None:
name = uid[len(prefix):]
fields = {
directory.fieldName.recordType: recordType,
directory.fieldName.uid: uid,
directory.fieldName.shortNames: [name],
directory.fieldName.fullNames: [name],
directory.fieldName.hasCalendars: True,
directory.fieldName.hasContacts: False,
}
record = DirectoryRecord(directory, fields)
yield record.service.updateRecords([record], create=True)
print("Added '{}'".format(name))


if __name__ == "__main__":
main()
50 changes: 50 additions & 0 deletions doc/calendarserver_migrate_wiki.8
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.\"
.\" Copyright (c) 2006-2017 Apple Inc. All rights reserved.
.\"
.\" Licensed under the Apache License, Version 2.0 (the "License");
.\" you may not use this file except in compliance with the License.
.\" You may obtain a copy of the License at
.\"
.\" http://www.apache.org/licenses/LICENSE-2.0
.\"
.\" Unless required by applicable law or agreed to in writing, software
.\" distributed under the License is distributed on an "AS IS" BASIS,
.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
.\" The following requests are required for all man pages.
.Dd June 17, 2009
.Dt CALENDARSERVER_MIGRATE_WIKI 8
.Os
.Sh NAME
.Nm calendarserver_migrate_wiki
.Nd Calendar Server wiki migration utility
.Sh SYNOPSIS
.Nm
.Op Fl -config Ar file
.Op Fl -help
.Sh DESCRIPTION
.Nm
is a tool for migrating wiki principals to resource records
in the calendar server's internal directory.
.Pp
.Nm
should be run as a user with the same privileges as the Calendar
Server itself, as it needs to read and write data that belongs to the
server.
.Sh OPTIONS
.Bl -tag -width flag
.It Fl h, -help
Display usage information
.It Fl f, -config Ar FILE
Use the Calendar Server configuration specified in the given file.
Defaults to /etc/caldavd/caldavd.plist.
.El
.Sh FILES
.Bl -tag -width flag
.It /etc/caldavd/caldavd.plist
The Calendar Server configuration file.
.El
.Sh SEE ALSO
.Xr caldavd 8
1 change: 1 addition & 0 deletions support/Apple.make
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ install-commands::
calendarserver_export \
calendarserver_import \
calendarserver_manage_principals \
calendarserver_migrate_wiki \
calendarserver_purge_attachments \
calendarserver_purge_events \
calendarserver_purge_principals \
Expand Down
7 changes: 4 additions & 3 deletions txdav/common/datastore/test/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ def assertProvides(testCase, interface, provider):

def buildTestDirectory(
store, dataRoot, accounts=None, resources=None, augments=None,
proxies=None, serversDB=None, cacheSeconds=0,
proxies=None, serversDB=None, cacheSeconds=0, wikiEnabled=True
):
"""
@param store: the store for the directory to use
Expand Down Expand Up @@ -740,7 +740,7 @@ def buildTestDirectory(
)
wikiServiceInfo = ConfigDict(
{
"Enabled": True,
"Enabled": wikiEnabled,
"EndpointDescriptor": "tcp:host=localhost:port=4444",
}
)
Expand Down Expand Up @@ -786,7 +786,8 @@ def buildStoreAndDirectory(
self.store, config.DataRoot,
accounts=accounts, resources=resources,
augments=augments, proxies=proxies,
serversDB=serversDB, cacheSeconds=cacheSeconds
serversDB=serversDB, cacheSeconds=cacheSeconds,
wikiEnabled=config.Authentication.Wiki.Enabled
)
if extraUids:
for uid in extraUids:
Expand Down

0 comments on commit 21dc757

Please sign in to comment.