projects

« Previous section Next section »

UCloud Developer Guide / Legacy / Projects (Legacy) / Projects

Projects

The projects feature allow for collaboration between different users across the entire UCloud platform.

Rationale

This project establishes the core abstractions for projects and establishes an event stream for receiving updates about changes. Other services extend the projects feature and subscribe to these changes to create the full project feature.


⚠️ WARNING: The API listed on this page will likely change to conform with our API conventions. Be careful when building integrations. The following changes are expected:

  • RPC names will change to conform with the conventions

  • RPC request and response types will change to conform with the conventions

  • RPCs which return a page will be collapsed into a single browse endpoint

  • Some property names will change to be consistent with Resources


Definition

A project in UCloud is a collection of members which is uniquely identified by an id. All members are users identified by their username and have exactly one role. A user always has exactly one role. Each project has exactly one principal investigator (PI). The PI is responsible for managing the project, including adding and removing users.

RoleNotes

PI

The primary point of contact for projects. All projects have exactly one PI.

ADMIN

Administrators are allowed to perform some project management. A project can have multiple admins.

USER

Has no special privileges.

Table: The possible roles of a project, and their privileges within project management.

A project can be updated by adding/removing/changing any of its members. Such an update will trigger a new message on the event stream.

A project is sub-divided into groups:

Each project may have 0 or more groups. The groups can have 0 or more members. A group belongs to exactly one project, and the members of a group can only be from the project it belongs to.

Creating Projects and Sub-Projects

All projects created by end-users have exactly one parent project. Only UCloud administrators can create root-level projects, that is a project without a parent. This allows users of UCloud to create a hierarchy of projects. The project hierarchy plays a significant role in accounting.

Normal users can create a project through the grant application feature.

A project can be uniquely identified by the path from the root project to the leaf-project. As a result, the title of a project must be unique within a single project. titles are case-insensitive.

Permissions and memberships are not hierarchical. This means that a user must be explicitly added to every project they need permissions in. UCloud administrators can always create a sub-project in any given project. A setting exists for every project which allows normal users to create sub-projects.


Example: A project hierarchy

Figure 1: A storage hierarchy

Figure 1 shows a hierarchy of projects. Note that users deep in the hierarchy are not necessarily members of the projects further up in the hierarchy. For example, being a member of "IMADA" does not imply membership of "NAT". A member of "IMADA" can be a member of "NAT" but they must be explicitly added to both projects.

None of the projects share any resources. Each individual project will have their own home directory. The administrators, or any other user, of "NAT" will not be able to read/write any files of "IMADA" unless they have explicitly been added to the "IMADA" project.

The Project Context

All requests in UCloud are executed in a particular context. The header of every request defines the context. For the HTTP backend this is done in the Project header. The absence of a project implies that the request is executed in the personal project context, also called My Workspace on UCloud.

Figure 2: The UCloud user interface allows you to select context through a dropdown in the navigation header.


Example: Accessing the project context from a microservice

implement(Descriptions.call) {
    val project: String? = ctx.project // null implies the personal project
    ok(service.doSomething(project))
}

Table of Contents

1. Remote Procedure Calls

2. Data Models

Remote Procedure Calls

allowsRenaming

allowsSubProjectRenaming

countSubProjects

RequestResponseError

fetchDataManagementPlan

listFavoriteProjects

listProjects

lookupById

lookupByIdBulk

lookupByPath

lookupPrincipalInvestigator

viewAncestors

RequestResponseError

viewMemberInProject

acceptInvite

archive

archiveBulk

changeUserRole

create

deleteMember

exists

invite

leaveProject

RequestResponseError

listIngoingInvites

listOutgoingInvites

listSubProjects

rejectInvite

rename

toggleRenaming

transferPiRole

updateDataManagementPlan

verifyMembership

RequestResponseError

viewProject

Data Models

IngoingInvite

data class IngoingInvite(
    val project: String,
    val title: String,
    val invitedBy: String,
    val timestamp: Long,
)
Properties


MemberInProject

data class MemberInProject(
    val role: ProjectRole?,
    val project: Project,
)
Properties


OutgoingInvite

data class OutgoingInvite(
    val username: String,
    val invitedBy: String,
    val timestamp: Long,
)
Properties


Project

data class Project(
    val id: String,
    val title: String,
    val parent: String?,
    val archived: Boolean,
    val fullPath: String?,
)
Properties


ProjectMember

data class ProjectMember(
    val username: String,
    val role: ProjectRole,
    val memberOfAnyGroup: Boolean?,
)
Properties


ProjectRole

enum class ProjectRole {
    PI,
    ADMIN,
    USER,
}
Properties


UserProjectSummary

data class UserProjectSummary(
    val projectId: String,
    val title: String,
    val whoami: ProjectMember,
    val needsVerification: Boolean,
    val isFavorite: Boolean,
    val archived: Boolean,
    val parent: String?,
    val ancestorPath: String?,
)
Properties


AcceptInviteRequest

data class AcceptInviteRequest(
    val projectId: String,
)
Properties


AllowsRenamingRequest

data class AllowsRenamingRequest(
    val projectId: String,
)
Properties


ArchiveBulkRequest

data class ArchiveBulkRequest(
    val projects: List<UserProjectSummary>,
)
Properties


ArchiveRequest

data class ArchiveRequest(
    val archiveStatus: Boolean,
)
Properties


ChangeUserRoleRequest

data class ChangeUserRoleRequest(
    val projectId: String,
    val member: String,
    val newRole: ProjectRole,
)
Properties


CreateProjectRequest

data class CreateProjectRequest(
    val title: String,
    val parent: String?,
    val principalInvestigator: String?,
)
Properties


DeleteMemberRequest

data class DeleteMemberRequest(
    val projectId: String,
    val member: String,
)
Properties


ExistsRequest

data class ExistsRequest(
    val projectId: String,
)
Properties


InviteRequest

data class InviteRequest(
    val projectId: String,
    val usernames: List<String>,
)
Properties


ListFavoriteProjectsRequest

data class ListFavoriteProjectsRequest(
    val user: String?,
    val itemsPerPage: Int,
    val page: Int,
    val archived: Boolean,
    val showAncestorPath: Boolean?,
)
Properties


ListIngoingInvitesRequest

data class ListIngoingInvitesRequest(
    val itemsPerPage: Int?,
    val page: Int?,
)
Properties


ListOutgoingInvitesRequest

data class ListOutgoingInvitesRequest(
    val itemsPerPage: Int?,
    val page: Int?,
)
Properties


ListProjectsRequest

data class ListProjectsRequest(
    val user: String?,
    val itemsPerPage: Int?,
    val page: Int?,
    val archived: Boolean?,
    val noFavorites: Boolean?,
    val showAncestorPath: Boolean?,
)
Properties


ListSubProjectsRequest

The base type for requesting paginated content.

data class ListSubProjectsRequest(
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

ConsistencyDescription

PREFER

Consistency is preferred but not required. An inconsistent snapshot might be returned.

REQUIRE

Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties


LookupByIdBulkRequest

data class LookupByIdBulkRequest(
    val ids: List<String>,
)
Properties


LookupByIdRequest

data class LookupByIdRequest(
    val id: String,
)
Properties


LookupByTitleRequest

data class LookupByTitleRequest(
    val title: String,
)
Properties


ProjectSearchByPathRequest

The base type for requesting paginated content.

data class ProjectSearchByPathRequest(
    val path: String,
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
    val includeFullPath: Boolean?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

ConsistencyDescription

PREFER

Consistency is preferred but not required. An inconsistent snapshot might be returned.

REQUIRE

Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties


RejectInviteRequest

data class RejectInviteRequest(
    val username: String?,
    val projectId: String,
)
Properties


RenameProjectRequest

data class RenameProjectRequest(
    val id: String,
    val newTitle: String,
)
Properties


ToggleRenamingRequest

data class ToggleRenamingRequest(
    val projectId: String,
)
Properties


TransferPiRoleRequest

data class TransferPiRoleRequest(
    val newPrincipalInvestigator: String,
)
Properties


UpdateDataManagementPlanRequest

data class UpdateDataManagementPlanRequest(
    val id: String,
    val dmp: String?,
)
Properties


ViewMemberInProjectRequest

data class ViewMemberInProjectRequest(
    val projectId: String,
    val username: String,
)
Properties


ViewProjectRequest

data class ViewProjectRequest(
    val id: String,
)
Properties


AllowsRenamingResponse

data class AllowsRenamingResponse(
    val allowed: Boolean,
)
Properties


ExistsResponse

data class ExistsResponse(
    val exists: Boolean,
)
Properties


FetchDataManagementPlanResponse

data class FetchDataManagementPlanResponse(
    val dmp: String?,
)
Properties


LookupPrincipalInvestigatorResponse

data class LookupPrincipalInvestigatorResponse(
    val principalInvestigator: String,
)
Properties


ViewMemberInProjectResponse

data class ViewMemberInProjectResponse(
    val member: ProjectMember,
)
Properties


Last updated