Space Proposal

Scope of change: Major
Champion Name: Evgeny Bogdanov
Spec Editors: Evgeny Bogdanov
Ref implementation: Apache Shindig 3.next

Background

Despite the fact that OpenSocial solves the problem of social media platform’s extensibility and gadgets portability, it has two major limitations. First, it is user-centric but does not take the user's context into account. In many social media platforms context is a crucial component and if gadgets were able to retrieve the user's context (from the hosting platform), it would greatly improve user’s experiences.

Conceptual changes

In the proposed extension a widget does not belong only to a person, it might belong to either a space or to a person. Such space or person we call the context. If a user is viewing another person's profile, then this profile is the context. If a user is viewing a space (a group, a community page, an event page, a course), then this space is the context. The opensocial's concept viewer is still valid here since only a person (not space) can view the widget. Though, the concept owner has to be redefined. Owner of a widget might be a space or a person in a sense that this widget belong to either a space or a person.

We suggest the word Space to be used. However, some other namings were proposed as well: "Community", "Group". We believe that the word Space covers broader area than "Community" or "Group" that are people centric. For example, event space or course space does not necessarily imply the community or a group of people.

Please refer to this paper on Contextual spaces for detailed information.

Difference between OpenSocial Space and Group

Space is a concept different from Group concept of OpenSocial.
Group is a way to tag people (collection of friends, relatives, etc). It is very similar to a circle concept of Google+. People in such group do not know that they are in the group, it is not the place shared with several members. Space represents another concept - a place where group of people gathered together for some activity: University course, collaborative project, event organization, discussion thread, etc. Every person in a space is aware about other participants. Imagine a group or an event on Facebook or discusion thread in google groups. If we add a gadget there it will be shared by people in that group or event. This is a Space concept.

Social graph clarification (Person vs Space)

Person
|-- his apps
|-- his connections (people with whom he is connected)
|-- his albums
|-- his activity streams
|-- his groups (friends, close friends, collegues)

Space
|-- its apps
|-- its connections (participants of a space)
|-- its albums
|-- its activity streams (actions within a space)
|-- its groups (members, admins, etc.)

Person can belong to different spaces.

APIs proposal

We provide here only JavaScript APIs with explanations to show what kind of requests are needed from widgets to work with spaces.
The initial proposal and first OpenSocial REST and JS APIs for Spaces can be found in the links section below. The APIs try to provide backward compatibility as much as posible.

Be aware that OpenSocial is planning to have IRI to identify resources.

0. security token

Security token should contain the appId information, which helps a server to identify the running app.

1. osapi.getContext (new)

osapi.getContext

Gadget should be able to know whether it belongs to a space or to a person and their respective ids.
This API retrieves info about where widget lives

osapi.getContext(function(context){
  context.id; // IRI id of the item
  context.service; // "people" or "spaces"
  context.object; // object that contains info about Space or Person
});

2. osapi.people

osapi.people.getViewer

Get the user who looks at widget at the moment (Viewer)

osapi.people.getViewer().execute(function(viewer){
  viewer.id;
  viewer.displayName;
});

osapi.people.get

(new) Get a list of members in a space with IRI = example.org/spaces/18

osapi.people.get({userId: "example.org/spaces/18", groupId: "@members"}).execute(function(response){
  response[0].displayName;
});

Get space owners (or members)

Get a list of owners in a space.

osapi.groups.get({id: "example.org/spaces/18"}).execute(function(groups){
  // groups[0].id - owners = "ID49"
  // groups[1].id - members = "ID50"
  osapi.people.get({groupId: groups[0].id}).execute(function(owners){
    owners[0].displayName; // owners of a space with IRI = "example.org/space/18"
  });
});

3. osapi.spaces (new)

osapi.spaces.get

(new) Get a list of spaces for a person or for a space

osapi.spaces.get({resourceId: "example.org/people/john.doe"}).execute(function(response){
  response[0].displayName;
});

4. osapi.apps (new)

Such API should be introduced to OpenSocial. App-Id exists in OpenSocial but is never defined.
Also the identification for API should be revised. It is quite possible that user would like to add few
gadgets with the same URL on his page or to a space. Consider an example of an RSS gadget: a user adds two gadgets
with the same URL and sets different RSS links in different gadgets.

osapi.apps.get

(new) Get list of apps for a person or for a space

osapi.apps.get({resourceId: "example.org/space/18"}).execute(function(response){
  response[0].displayName;
});

osapi.apps.getCurrent

(new) Get the currently running app

osapi.apps.getCurrent().execute(function(curApp){
  curApp.displayName;
});

osapi.apps.getParent

(new) Get a parent of the running app (either space or person)

osapi.apps.getParent().execute(function(parent){
  parent.displayName;
  parent.id;
});

5. osapi.appdata

Appdata should be saved either for widget context (space or person where widget belongs) or per
any other user (viewer, for example).

osapi.appdata.update

Update/Save appdata for a space or for a person

osapi.appdata.update({resourceId: "example.org/spaces/1",  data: {key: value}).execute(function(){
});

osapi.appdata.get

Get appdata from the container for a space or for a person

osapi.appdata.get({resourceId: "example.org/spaces/1", keys: ['key']).execute(function(data){
  data['user1']['key'];
});

6. osapi.activitystreams

ActivityStreams can belong to a space or a person.

osapi.activitystreams.get

Retrieve activities of people within a space.

osapi.activitystreams.get({resourceId: "example.org/spaces/1", count: 20}).execute(function(){
});

7. osapi.albums / osapi.mediaitems

Albums and mediaitems can be associated with a space or a person.
Once albums/mediaitems are replaces with CMIS's folders/files, the new API will be adapted accordingly.

osapi.albums.get

Retrieve albums existing in a space.

osapi.albums.get({resourceId: "example.org/spaces/1"}).execute(function(){
});

8. osapi.groups

Groups represent a collection of people. They can exist for both a person (friends, collegues, etc) and a space (admins, owners, participants, viewers).

A Space can have many different groups. The groups can be created and deleted. Below is a list of generic (container-independent) groups for a space:

@members - all people who explicitely joined the space

@owners - space members with unlimited rights

@contributors - people who contribute content to the space (but less rights than owners)

@creator - the creator of a space

@followers & @following

osapi.groups.get

Retrieve groups existing in a space

osapi.groups.get({resourceId: "example.org/spaces/1"}).execute(function(results){
  // results = [{id: "1", name: "members"},{id: "2", name: "owners"}]
});

Shindig patch with spaces

Shindig-2.5 is taken as a base. Patch is attached (with tests)

Links

Space proposal draft based on OpenSocial 2.5 spec

Patch with spaces for OpenSocial spec 2.5

Space proposal issue for OpenSocial spec

Reference implementation (Apache Shindig 3.0)

Old proposal from wiki.opensocial.org