// GetPendingInvitations is the handler for GET /organizations/{globalid}/invitations
// Get the list of pending invitations for users to join this organization.
func (api OrganizationsAPI) GetPendingInvitations(w http.ResponseWriter, r *http.Request) {
	globalid := mux.Vars(r)["globalid"]

	invitationMgr := invitations.NewInvitationManager(r)

	requests, err := invitationMgr.GetPendingByOrganization(globalid)

	if err != nil {
		log.Error("Error in GetPendingByOrganization: ", err.Error())
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	pendingInvites := make([]organization.Invitation, len(requests), len(requests))
	for index, request := range requests {
		pendingInvites[index] = organization.Invitation{
			Role:    request.Role,
			User:    request.User,
			Created: request.Created,
		}
	}
	w.Header().Set("Content-Type", "application/json")

	json.NewEncoder(w).Encode(pendingInvites)
}
Beispiel #2
0
// Get the list of notifications, these are pending invitations or approvals
// It is handler for GET /users/{username}/notifications
func (api UsersAPI) usernamenotificationsGet(w http.ResponseWriter, r *http.Request) {
	username := mux.Vars(r)["username"]

	type NotificationList struct {
		Approvals        []invitations.JoinOrganizationInvitation `json:"approvals"`
		ContractRequests []contract.ContractSigningRequest        `json:"contractRequests"`
		Invitations      []invitations.JoinOrganizationInvitation `json:"invitations"`
	}
	var notifications NotificationList

	invititationMgr := invitations.NewInvitationManager(r)

	userOrgRequests, err := invititationMgr.GetByUser(username)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	notifications.Invitations = userOrgRequests

	// TODO: Get Approvals and Contract requests
	notifications.Approvals = []invitations.JoinOrganizationInvitation{}
	notifications.ContractRequests = []contract.ContractSigningRequest{}

	w.Header().Set("Content-type", "application/json")
	json.NewEncoder(w).Encode(&notifications)

}
// Accept membership in organization
// It is handler for POST /users/{username}/organizations/{globalid}/roles/{role}
func (api UsersusernameorganizationsAPI) globalidrolesrolePost(w http.ResponseWriter, r *http.Request) {
	username := mux.Vars(r)["username"]
	role := mux.Vars(r)["role"]
	organization := mux.Vars(r)["globalid"]

	var j invitations.JoinOrganizationInvitation

	if err := json.NewDecoder(r.Body).Decode(&j); err != nil {
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	orgReqMgr := invitations.NewInvitationManager(r)

	orgRequest, err := orgReqMgr.Get(username, organization, role, invitations.RequestPending)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	// TODO: Save member
	orgMgr := organizationpackage.NewManager(r)

	if org, err := orgMgr.GetByName(organization); err != nil {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	} else {
		if invitations.RoleOwner == orgRequest.Role {
			// Accepted Owner role
			if err := orgMgr.SaveOwner(org, username); err != nil {
				log.Error("Failed to save owner: ", username)
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		} else {
			// Accepted member role
			if err := orgMgr.SaveMember(org, username); err != nil {
				log.Error("Failed to save member: ", username)
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		}
	}

	orgRequest.Status = invitations.RequestAccepted

	if err := orgReqMgr.Save(orgRequest); err != nil {
		log.Error("Failed to update org request status: ", orgRequest.Organization)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-type", "application/json")
	w.WriteHeader(http.StatusCreated)

	json.NewEncoder(w).Encode(orgRequest)
}
// AddOrganizationOwner It is handler for POST /organizations/{globalid}/owners
func (api OrganizationsAPI) AddOrganizationOwner(w http.ResponseWriter, r *http.Request) {
	globalid := mux.Vars(r)["globalid"]

	var s searchMember

	if err := json.NewDecoder(r.Body).Decode(&s); err != nil {
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	orgMgr := organization.NewManager(r)

	org, err := orgMgr.GetByName(globalid)
	if err != nil {
		if err == mgo.ErrNotFound {
			http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		} else {
			handleServerError(w, "getting organization", err)
		}
		return
	}

	u, err := SearchUser(r, s.SearchString)
	if err != nil {
		log.Error(err)
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}
	for _, membername := range org.Owners {
		if membername == u.Username {
			http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict)
			return
		}
	}
	// Create JoinRequest
	invitationMgr := invitations.NewInvitationManager(r)

	orgReq := &invitations.JoinOrganizationInvitation{
		Role:         invitations.RoleOwner,
		Organization: globalid,
		User:         u.Username,
		Status:       invitations.RequestPending,
		Created:      db.DateTime(time.Now()),
	}

	if err := invitationMgr.Save(orgReq); err != nil {
		log.Error("Error inviting owner: ", err.Error())
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)

	json.NewEncoder(w).Encode(orgReq)
}
// It is handler for POST /organizations/{globalid}/members
func (api OrganizationsAPI) globalidownersPost(w http.ResponseWriter, r *http.Request) {
	globalid := mux.Vars(r)["globalid"]

	var m member

	if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	orgMgr := NewManager(r)

	org, err := orgMgr.GetByName(globalid)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	// Check if user exists
	userMgr := user.NewManager(r)

	if ok, err := userMgr.Exists(m.Username); err != nil || !ok {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	for _, membername := range org.Owners {
		if membername == m.Username {
			http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict)
			return
		}
	}
	// Create JoinRequest
	invitationMgr := invitations.NewInvitationManager(r)

	orgReq := &invitations.JoinOrganizationInvitation{
		Role:         invitations.RoleOwner,
		Organization: globalid,
		User:         m.Username,
		Status:       invitations.RequestPending,
	}

	if err := invitationMgr.Save(orgReq); err != nil {
		log.Error("Error inviting owner: ", err.Error())
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)

	json.NewEncoder(w).Encode(orgReq)
}
// It is handler for DELETE /users/{username}/organizations/{globalid}/roles/{role}
func (api UsersusernameorganizationsAPI) globalidrolesroleDelete(w http.ResponseWriter, r *http.Request) {
	username := mux.Vars(r)["username"]
	role := mux.Vars(r)["role"]
	organization := mux.Vars(r)["globalid"]

	orgReqMgr := invitations.NewInvitationManager(r)

	orgRequest, err := orgReqMgr.Get(username, organization, role, invitations.RequestPending)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	orgMgr := organizationpackage.NewManager(r)

	if org, err := orgMgr.GetByName(organization); err != nil {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	} else {
		if invitations.RoleOwner == orgRequest.Role {
			// Rejected Owner role
			if err := orgMgr.RemoveOwner(org, username); err != nil {
				log.Error("Failed to remove owner: ", username)
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		} else {
			// Rejected member role
			if err := orgMgr.RemoveMember(org, username); err != nil {
				log.Error("Failed to reject member: ", username)
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		}
	}

	orgRequest.Status = invitations.RequestRejected

	if err := orgReqMgr.Save(orgRequest); err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}
Beispiel #7
0
//FilterPossibleScopes filters the requestedScopes to the relevant ones that are possible
// For example, a `user:memberof:orgid1` is not possible if the user is not a member the `orgid1` organization and there is no outstanding invite for this organization
// If allowInvitations is true, invitations to organizations allows the "user:memberof:organization" as possible scopes
func (service *Service) FilterPossibleScopes(r *http.Request, username string, requestedScopes []string, allowInvitations bool) (possibleScopes []string, err error) {
	possibleScopes = make([]string, 0, len(requestedScopes))
	orgmgr := organizationdb.NewManager(r)
	invitationMgr := invitations.NewInvitationManager(r)
	for _, rawscope := range requestedScopes {
		scope := strings.TrimSpace(rawscope)
		if strings.HasPrefix(scope, "user:memberof:") {
			orgid := strings.TrimPrefix(scope, "user:memberof:")
			isMember, err := orgmgr.IsMember(orgid, username)
			if err != nil {
				return nil, err
			}
			if isMember {
				possibleScopes = append(possibleScopes, scope)
				continue
			}
			isOwner, err := orgmgr.IsOwner(orgid, username)
			if err != nil {
				return nil, err
			}
			if isOwner {
				possibleScopes = append(possibleScopes, scope)
				continue
			}
			if allowInvitations {
				hasInvite, err := invitationMgr.HasInvite(orgid, username)
				if err != nil {
					log.Error("FilterPossibleScopes: Error while checking if user has invite for organization: ", err)
					return nil, err
				}
				if hasInvite {
					possibleScopes = append(possibleScopes, scope)
				}
			}
		} else {
			possibleScopes = append(possibleScopes, scope)
		}
	}
	return
}
// DeleteOrganization is the handler for DELETE /organizations/{globalid}
// Deletes an organization and all data linked to it (join-organization-invitations, oauth_access_tokens, oauth_clients, authorizations)
func (api OrganizationsAPI) DeleteOrganization(w http.ResponseWriter, r *http.Request) {
	globalid := mux.Vars(r)["globalid"]
	orgMgr := organization.NewManager(r)
	logoMgr := organization.NewLogoManager(r)
	if !orgMgr.Exists(globalid) {
		writeErrorResponse(w, http.StatusNotFound, "organization_not_found")
		return
	}
	suborganizations, err := orgMgr.GetSubOrganizations(globalid)
	if handleServerError(w, "fetching suborganizations", err) {
		return
	}
	if len(suborganizations) != 0 {
		writeErrorResponse(w, 422, "organization_has_children")
		return
	}
	err = orgMgr.Remove(globalid)
	if handleServerError(w, "removing organization", err) {
		return
	}
	// Remove the organizations as a member/ an owner of other organizations
	organizations, err := orgMgr.AllByOrg(globalid)
	if handleServerError(w, "fetching organizations where this org is an owner/a member", err) {
		return
	}
	for _, org := range organizations {
		err = orgMgr.RemoveOrganization(org.Globalid, globalid)
		if handleServerError(w, "removing organizations as a member / an owner of another organization", err) {
			return
		}
	}
	if logoMgr.Exists(globalid) {
		err = logoMgr.Remove(globalid)
		if handleServerError(w, "removing organization logo", err) {
			return
		}
	}
	orgReqMgr := invitations.NewInvitationManager(r)
	err = orgReqMgr.RemoveAll(globalid)
	if handleServerError(w, "removing organization invitations", err) {
		return
	}

	oauthMgr := oauthservice.NewManager(r)
	err = oauthMgr.RemoveTokensByGlobalId(globalid)
	if handleServerError(w, "removing organization oauth accesstokens", err) {
		return
	}
	err = oauthMgr.DeleteAllForOrganization(globalid)
	if handleServerError(w, "removing client secrets", err) {
		return
	}
	err = oauthMgr.RemoveClientsById(globalid)
	if handleServerError(w, "removing organization oauth clients", err) {
		return
	}
	userMgr := user.NewManager(r)
	err = userMgr.DeleteAllAuthorizations(globalid)
	if handleServerError(w, "removing all authorizations", err) {
		return
	}
	err = oauthMgr.RemoveClientsById(globalid)
	if handleServerError(w, "removing organization oauth clients", err) {
		return
	}
	l2faMgr := organization.NewLast2FAManager(r)
	err = l2faMgr.RemoveByOrganization(globalid)
	if handleServerError(w, "removing organization 2FA history", err) {
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
// AddOrganizationMember Assign a member to organization
// It is handler for POST /organizations/{globalid}/members
func (api OrganizationsAPI) AddOrganizationMember(w http.ResponseWriter, r *http.Request) {
	globalid := mux.Vars(r)["globalid"]

	var s searchMember

	if err := json.NewDecoder(r.Body).Decode(&s); err != nil {
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	orgMgr := organization.NewManager(r)

	org, err := orgMgr.GetByName(globalid)
	if err != nil {
		if err == mgo.ErrNotFound {
			http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		} else {
			handleServerError(w, "getting organization", err)
		}
		return
	}

	// Check if user exists
	u, err := SearchUser(r, s.SearchString)
	if err != nil {
		if err != mgo.ErrNotFound {
			log.Error(err)
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}
	for _, membername := range org.Members {
		if membername == u.Username {
			http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict)
			return
		}
	}

	for _, membername := range org.Owners {
		if membername == u.Username {
			http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict)
			return
		}
	}

	// Create JoinRequest
	invitationMgr := invitations.NewInvitationManager(r)
	count, err := invitationMgr.CountByOrganization(globalid)
	if err != nil {
		log.Error(err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	if count >= MAX_AMOUNT_INVITATIONS_PER_ORGANIZATION {
		log.Error("Reached invitation limit for organization ", globalid)
		writeErrorResponse(w, 422, "max_amount_of_invitations_reached")
		return
	}
	orgReq := &invitations.JoinOrganizationInvitation{
		Role:         invitations.RoleMember,
		Organization: globalid,
		User:         u.Username,
		Status:       invitations.RequestPending,
		Created:      db.DateTime(time.Now()),
	}

	if err := invitationMgr.Save(orgReq); err != nil {
		log.Error("Error inviting member: ", err.Error())
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)

	json.NewEncoder(w).Encode(orgReq)
}