Skip to content

Commit

Permalink
change invite/join to point at #232 instead
Browse files Browse the repository at this point in the history
  • Loading branch information
meejah committed Aug 4, 2020
1 parent fd6b949 commit 78f2d6b
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 105 deletions.
52 changes: 24 additions & 28 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,38 +153,31 @@ Inviting Participant Devices

A new participant device is invited to collaborate on a magic folder
using the ``magic-folder invite`` command. This produces an "invite
code" which **contains secret information**. It must be shared in a
secure way; anyone viewing the "invite code" can impersonate the
invitee (if they also have access to the Tahoe Grid).
code" which is a one-time code. This code should be communicated
securely to the invitee. The code will allow the invitee's device to
establish a connection to this device and exchange details. Thus, the
code can only be used while this device is connected to the
Internet. The code may only be used once, for a single invitee.

.. code-block:: console
$ magic-folder --config ./foo invite --name default bob
$ magic-folder --config ./foo invite --name default
An invitation code is created using an existing magic folder (``--name
default`` above) and a nickname for the new participant device
(``bob`` above). The magic-folder identified must have been created on
this device. The nickname is assigned to the participant device in
the magic folder configuration and grid state.

**Technical details**: A new mutable directory is created in the Tahoe
LAFS grid, producing a write-capability. This is "attenuated" to a
read-capability. This read-capability is written into the "collective
Distributed Mutable Diractory (DMD)" with the invitee's name; this
allows other magic-folder participants to notice this new participant
when they next download it.

The invite-code includes the write-capability for the participant's
"personal DMD"; this is where updates produced by the invitee will be
written. Notice that the administrator of the magic-folder (the one
device holding the write-capability for the "collective DMD") could
retain the invitee's "personal DMD" write-capbility and use it to
impersonate that participant. **The invite-code MUST be communicated
securely to the invitee**.

Another part of the invite-code is a read-capability for the
"collective DMD" allowing the new participant to learn of all other
participants.
default`` above). The magic-folder identified must have been created on
this device.

Once the invitee runs ``magic-folder join`` (see below) the two
devices will connect and exchange some information; this will complete
the invitation. The "invite" command won't exit until the invitee has
actually completed and will print out some details. If you pass
``--no-wait`` then the command will exist immediately (although the
invite will still be valid).

Invites are valid until the magic-folder daemon stops running or until
the default number of minutes pass (whichever is sooner). See the
``--timeout`` for the default (or you can pass a different number of
mintues if you prefer).


Joining a Magic Folder
Expand All @@ -203,7 +196,10 @@ required is the path to a local directory. This is the directory to
which content will be downloaded and from which it will be uploaded.

You must choose a name to identify content from this device with
``--author``.
``--author``. The device which has invited you must also be connected
to the internet for the invite to work: once a connection is
established, the two devices exchange some information and the invite
is complete.

Further options are documented in ``magic-folder join --help``.

Expand Down
62 changes: 5 additions & 57 deletions src/magic_folder/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,71 +29,19 @@


@inlineCallbacks
def magic_folder_invite(config, folder_name, invitee_name, treq):
def magic_folder_invite(config, folder_name, treq):
"""
Invite a user identified by the nickname to a folder owned by the alias
:param GlobalConfigDatabase config: our configuration
:param unicode folder_name: The name of an existing magic-folder
:param unicode invitee_name: The nickname for the new participant
:param HTTPClient treq: An ``HTTPClient`` or similar object to use to make
the queries.
:return Deferred[unicode]: A secret invitation code.
:return Deferred[unicode]: A secret magic-wormhole invitation code.
"""
# XXX probably want to pass this in, instead of "treq"?
tahoe_client = create_tahoe_client(config.tahoe_client_url, treq)

# get configuration for this magic-folder (or error if it doesn't
# exist)
try:
folder_config = config.get_magic_folder(folder_name)
except ValueError:
raise usage.UsageError(
u"No magic-folder named '{}'".format(folder_name)
)

if not folder_config.is_admin():
raise usage.UsageError(
u"This device is not the administrator for '{}'".format(folder_name)
)

# create an unlinked directory and get the dmd write-cap
dmd_write_cap = yield tahoe_client.create_mutable_directory()

# derive a dmd read-only cap from it.
dmd_readonly_cap = uri.from_string(dmd_write_cap.encode("utf8")).get_readonly().to_string()
if dmd_readonly_cap is None:
raise Exception("failed to diminish dmd write cap")

# Now, we need to create a link to the nickname from inside the
# collective to this read-cap. For that we will need to know the
# write-cap of the collective (which will only be true if we're
# the administrator device) so that a link can be created inside
# it.

# we already checked above that this is a write-cap using .is_admin()
magic_write_cap = folder_config.collective_dircap
magic_readonly_cap = uri.from_string(magic_write_cap.encode("utf8")).get_readonly().to_string()

# ...we're adding a sub-directory to the global DMD; the name of
# this sub-directory is the invitee's name and it points to the
# mutable directory we created for them (which will be included in
# the invite code)

yield tahoe_client.add_entry_to_mutable_directory(
magic_write_cap,
invitee_name,
dmd_readonly_cap,
)

invite_code = "{}{}{}".format(
magic_readonly_cap,
INVITE_SEPARATOR,
dmd_write_cap,
)

returnValue(invite_code)
# FIXME TODO
# see https://github.com/LeastAuthority/magic-folder/issues/232
raise NotImplemented
23 changes: 3 additions & 20 deletions src/magic_folder/join.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,6 @@ def magic_folder_join(config, invite_code, local_dir, name, poll_interval, autho
:return: None or exception is raised on error.
"""
fields = invite_code.split(INVITE_SEPARATOR)
if len(fields) != 2:
raise usage.UsageError("Invalid invite code.")
magic_readonly_cap, dmd_write_cap = fields

if name in config.list_magic_folders():
raise Exception(
"This client already has a magic-folder named '{}'".format(name)
)

author = create_local_author(author_name)
config.create_magic_folder(
name,
local_dir,
config.get_default_state_path(name),
author,
magic_readonly_cap,
dmd_write_cap,
poll_interval,
)
# FIXME TODO
# https://github.com/LeastAuthority/magic-folder/issues/232
raise NotImplemented

0 comments on commit 78f2d6b

Please # to comment.