Sleds/cppcore/cppcoreobjects/permissions.h

374 lines
14 KiB
C
Raw Normal View History

2025-03-13 21:28:38 +00:00
// Copyright (c) 2013, IOnU Security, Inc.
// Copyright (c) 2016, Sequence Logic, Inc. All rights reserved.
/**
* The Permissions class...
*/
#ifndef PERMISSIONS
#define PERMISSIONS
#include "../../libeye/eyeconstants.h"
#include <vector>
#include <set>
#include <map>
#include <memory>
#include <string>
// If this is being included in the shell extension, don't decorate the class with DLL export/import
#if defined(WIN32) && !defined(SL_SHELL_EXT)
#ifdef SL_CPPCORE_DLLEXPORT
#define SL_CPPCORE_EXPORT __declspec(dllexport)
#else
#define SL_CPPCORE_EXPORT __declspec(dllimport)
#endif
#else
#define SL_CPPCORE_EXPORT
#endif
namespace sequencelogic
{
class CloudGuardURN;
typedef std::set<CloudGuardURN> CloudGuardURNSet;
typedef CloudGuardURNSet::iterator CloudGuardURNSetIter;
typedef std::map<CloudGuardURN, CloudGuardURNSet> CloudGuardURNToURNSetMap;
typedef CloudGuardURNToURNSetMap::iterator CloudGuardURNToURNSetMapIter;
typedef CloudGuardURNToURNSetMap::const_iterator CloudGuardURNToURNSetMapCIter;
class Permissions;
typedef std::shared_ptr<Permissions> PermissionsPtr;
class JSONArray;
typedef std::shared_ptr<JSONArray> JSONArrayPtr;
class JSONObject;
typedef std::shared_ptr<JSONObject> JSONObjectPtr;
#if defined(WIN32) || defined(_WIN32)
#pragma warning(push)
#pragma warning(disable:4251 4275) // Disable the dumbass XXXX needs to have dll-interface.
#endif
/**
* Permissions (the object and the concept) both track user rights to operations, and provide a host
* of methods to manipulate rights.
* <p>Every permissions object has an owner, which is a PMO UUID; this is not a full URN, but just the office
* identifier portion. Ownership cannot be changed, at present. So this also signifies the creator of
* any given permission object.
* <p>An authority can be set on a permissions instance. The authority is the PMO UUID on whose behalf
* a change is requested. Often, the owner and authority are the same ID. However, another user may be the
* authority, attempt to assign a rights value, and will only succeed if the authority in question has
* the Assign right for the actual right in question.
* <p>The rights are: read, readAssign, write, writeAssign, admin, adminAssign, doorway (out) and doorwayAssign
* and stream/streamAssign. Various methods below set, assign, check and validate these rights.
* <p>There is also hide and hideAssign which indicate that a file exists but cannot be displayed.
* <p>Any given right can be granted to "owner", a specific PMO UUID or a group identifier:
* <code>g@{van}:{pmo}:{device}:{groupDocID}</code>. Note that this form is not a fully qualified URN
* (it lacks the prefix "urn:sl:"). The group document URN identifies a set of users belonging to a group.
*
* @author tim, viggy
*/
class SL_CPPCORE_EXPORT Permissions
{
public:
static const char* PERMISSION_KEYS[];
static const int NUM_PERMISSION_KEYS;
static const char SIGNATURE_KEY[];
/**
* Construct with default permissions.
*/
Permissions();
Permissions(const PermissionsPtr pOrigObj);
Permissions(const std::string &permStr);
virtual ~Permissions() {}
Permissions(const Permissions &origObj);
Permissions(const JSONObject &origObj);
Permissions& operator=(const Permissions &rhs);
/**
* Comparison.
*/
bool operator==(const Permissions &rhs);
/**
* Construct from a parent object
* @param pParent
* @return
*/
static PermissionsPtr createFromParent(const JSONObject &parent);
/**
* Construct from a device local file.
* @param fileName
* @param ownerAuthority
* @return
*/
static PermissionsPtr createFromDeviceFile(const std::string &fileName, const CloudGuardURN &ownerAuthority);
/**
* Construct from a flattened non-json string.
* @param owner
* @param authority
* @param string read=something,else | write=something ...
* @return
*/
static PermissionsPtr createFromFlatString(const std::string &owner, const std::string &string, const std::string &authority = "");
/**
* Creates a Permission object that references ONLY a single office. Typically this office
* will be the client office.
* @param pmoUrn
* @return
*/
static PermissionsPtr createFromOffice(const CloudGuardURN &pmoUrn);
/**
* Creates a Permission object that references a team
* @param teamUrn
* @return
*/
static PermissionsPtr createFromTeam(const CloudGuardURN &teamUrn);
/**
* Given two or more URNs, create Permissions object.
* At least one URN must NOT be a group. This function *will* reorder the vector (sorted by URN string)
* @param urns - at least two, with at least one being a non-group
* @return
*/
static PermissionsPtr createFromUrnList(std::vector<CloudGuardURN> &urns);
/**
* Incoming userPermissions is of form:
* <pre>
* {
* "id": "me",
* "role": "owner",
* "selfLink": "https:\/\/www.googleapis.com\/drive\/v2\/files\/0ByK--JTHkV6AZzB5LXlpR2RnMU0\/permissions\/me",
* "type": "user",
* "etag": "\"Q0cVodxX8sh4vfxZTlOyWcmmc0k\/m7evUIvideYSbzR6BMwMo0JTKWU\"",
* "kind": "drive#permission"
* },
* </pre>
* @param userPermissions
* @param ownerAuthority - if google perms indicate ownership of file then this will be assigned to our
* owner and authority; if we are NOT the owner, then those fields are NOT set
* @return
* @see https://developers.google.com/drive/v2/reference/permissions#resource
*/
static PermissionsPtr createFromGoogleUserPermissions(const std::shared_ptr<JSONObject> pUserPermissions, const CloudGuardURN &ownerAuthority);
/**
* Guarantee consistent ordering of hash keys...
* @return
*/
std::string toOrderedString() const;
/**
* For UX display of short rights string.
* @param user
* @return
*/
std::string toRightsString(const std::string &user) const;
std::string rightsString(const std::string &perm, const std::string &user) const;
std::string getDigest() { return getPermittedRightsSignature(); }
std::string getPermittedRightsSignature();
/**
* Gets a 12 character digest (one way hash) of the ordered permissions. Identical (equivalent ignoring
* key ordering JSON issues and ignoring permissions) permissions will thus
* have the same digest value.
* @return
*/
std::string getSignature(const CloudGuardURN &van) const;
std::string getSignaturePath(const CloudGuardURN &van) const;
void getPermittedItems(const CloudGuardURN &van, JSONArray &permittedItems) const;
std::string getOrderedReferences(const CloudGuardURN &van) const;
/**
* Gets a set of referenced user values. This does NOT reference 'mbrs' data but inspects
* individual rights.
* @param van tell us what van we are operating within
* @param Return set, possibly empty list of group document URN's
*/
void getReferencedUsers(const CloudGuardURN &van, CloudGuardURNSet &referencedUsers) const;
/**
* Gets a set of referenced group values. This does NOT reference 'mbrs' data but inspects
* individual rights.
* @param Return set, possibly empty list of group document URN's
*/
void getReferencedGroups(CloudGuardURNSet &referencedGroups) const;
/**
* Get all references, both users and groups (you need to check the group device ID to see what's
* a group and what is a normal user).
* @param van
*/
void getAllReferences(const CloudGuardURN &van, CloudGuardURNSet &allReferences) const;
/**
* Same results as getAllReferences but in JSONArray format with each element being a string.
* @param van
* @return
*/
JSONArrayPtr getAllReferencesAsStringArray (const CloudGuardURN &vanUrn) const;
/**
* Updates members array by adding all unique UUID values referenced by this object and
* any referenced groups. Membership simply means that you are named in a *some* permission.
* It's useful for indexing and having a list of everyone who can interact with a document.
*
* @param van - tell us van we are operating within
* @param groupMap - null (no group resolution) or map of group doc URN to UUID values.
* @param Return set of members (PMO urn's) - internal 'mbrs' array is also set on this object
*/
void updateMembers(const CloudGuardURN &van, const CloudGuardURNToURNSetMap &groupMap, CloudGuardURNSet &curMembers);
std::string getAuthority() const { return _authority; }
void setAuthority(const std::string &authority) { _authority = authority; }
void setOwner(const std::string &owner);
std::string getOwner() const;
std::string getName() const;
void setName(const std::string &name);
void setType(const std::string &type);
std::string getType() const;
bool isGroup() const;
bool canRead(const std::string &user) const;
bool canWrite(const std::string &user) const;
bool isAdmin(const std::string &user) const;
bool canDoorway(const std::string &user) const;
bool canStream(const std::string &user) const;
bool canHide(const std::string &user) const;
bool assignRead(const std::string &user);
bool assignRead(const std::vector<std::string> &users);
bool assignWrite(const std::string &user);
bool assignWrite(const std::vector<std::string> &users);
bool assignAdmin(const std::string &user);
bool assignAdmin(const std::vector<std::string> &users);
bool assignDoorway(const std::string &user);
bool assignDoorway(const std::vector<std::string> &users);
bool assignStream(const std::string &user);
bool assignStream(const std::vector<std::string> &users);
bool assignHide(const std::string &user);
bool assignHide(const std::vector<std::string> &users);
PermissionsPtr merge(const Permissions &permissions);
/**
* Merge, or copy, perms into this permissions object.
*/
void simpleMerge(const Permissions &perms);
/**
* Remove the indicated permission, ignoring any access/assignment rights checking.
* @param perm
* @param user
*/
void remove(const std::string &perm, const std::string &user);
/**
* Set the indicated permission, ignoring any access/assignment rights checking.
* @param perm
* @param user - no validation is performed on this value
*/
void set(const std::string &perm, const std::string &user);
/**
* Does the user have the indicated permission?
* @param obj
* @param perm either a perm (read) or assignment (readAssign)
* @param user
* @return
*/
static bool can(const Permissions &obj, const std::string &perm, const std::string &user, std::string *pWhyReturn = NULL);
/**
* Can the user assign a permission
* @param obj
* @param perm simple perm never with assignment suffix
* @param user
* @return
*/
static bool canAssign(const Permissions &obj, const std::string &perm, const std::string &user)
{ return canAssign(obj._pData.get(), perm, user); }
/**
* Assign 'perm' to 'user', but only if 'auth' has assign* priv.
* @param obj - Permissions object
* @param perm -
* @param auth
* @param user - no validation is performed on this value
* @return true if assignment successful; false if it was not
*/
static bool assign(Permissions &obj, const std::string &perm, const std::string &auth, const std::string &user)
{ return assign(obj._pData.get(), perm, auth, user); }
static bool assign(Permissions &obj, const std::string &perm, const std::string &auth, const std::vector<std::string> &users)
{ return assign(obj._pData.get(), perm, auth, users); }
/**
* Set a value, and it's 'assign' counterpart.
*/
void setWithAssign(const std::string &perm, const std::string &user);
void removeWithAssign(const std::string &perm, const std::string &user);
/**
* Accessors for the underlying JSON object.
*/
bool HasMember(const std::string &memberName) const;
std::string toString() const;
bool LoadFromFile(const std::string &fileName);
bool SaveToFile(const std::string &fileName) const;
JSONArray getUserArray(const std::string &arrayName) const;
void setKeys(const JSONArray &keys);
bool hasKeys() const;
void clearKeys();
bool isEmpty() const;
/**
* Get a list of users, based on a permission key.
*/
void getUsers(const CloudGuardURN &van, const std::string &key, std::vector<CloudGuardURN> &users) const;
std::string getUserAndGroupSig(const CloudGuardURN &van) const;
private:
std::string _authority;
JSONObjectPtr _pData;
void collectMembers(const CloudGuardURN &van, const CloudGuardURNToURNSetMap &groupMap, const JSONArray &permArray, CloudGuardURNSet &mbrs);
std::string getPermittedRightsSig() const;
void mergeDefaultPermissions();
static bool can(const JSONObject *pObj, const std::string &perm, const std::string &user, bool bRemove, std::string *pWhyReturn = NULL);
static bool canAssign(const JSONObject *pObj, const std::string &perm, const std::string &user);
static bool assign(JSONObject *pObj, const std::string &perm, const std::string &auth, const std::string &user);
static bool assign(JSONObject *pObj, const std::string &perm, const std::string &auth, const std::vector<std::string> &users);
static void mergePermissions(Permissions *pDest, const Permissions &src, bool bAssign);
};
#if defined(WIN32) || defined(_WIN32)
#pragma warning(pop)
#endif
};
#endif