/// <summary> /// Returns the groups that the <see cref="DirectoryObject"/> is a member of, among the groups /// requested. /// </summary> /// <param name="directoryObject">Object whose membership needs to be checked.</param> /// <param name="groupIds">Group ids.</param> /// <returns> /// List of groups that the object is a part of (from the list of groupIds provided) /// </returns> public virtual IList <string> CheckMemberGroups(GraphObject graphObject, IList <string> groupIds) { Utils.ValidateGraphObject(graphObject, "graphObject"); Utils.ThrowIfNullOrEmpty(groupIds, "groupIds"); List <string> memberGroups = new List <string>(); Uri requestUri = Utils.GetRequestUri <DirectoryObject>( this, graphObject.ObjectId, Constants.ActionCheckMemberGroups); Logger.Instance.Info("POSTing to {0}", requestUri); Dictionary <string, IList <string> > parameters = new Dictionary <string, IList <string> >(); parameters["groupIds"] = groupIds; string requestJson = JsonConvert.SerializeObject(parameters); string responseJson = this.ClientConnection.UploadString( requestUri, HttpVerb.POST, requestJson, null, null); PagedResults <GraphObject> pagedResults = SerializationHelper.DeserializeJsonResponse <GraphObject>(responseJson, requestUri); memberGroups.AddRange(pagedResults.MixedResults); return(memberGroups); }
public virtual PagedResults <GraphObject> GetLinkedObjects( GraphObject graphObject, LinkProperty linkProperty, string nextPageToken, int top) { Utils.ValidateGraphObject(graphObject, "graphObject"); Uri objectUri = Utils.GetRequestUri( this, graphObject.GetType(), graphObject.ObjectId, nextPageToken, top, Utils.GetLinkName(linkProperty)); if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add( new BatchRequestItem(HttpVerb.GET, true, objectUri, null, null)); return(null); } byte[] rawResponse = this.ClientConnection.DownloadData(objectUri, null); PagedResults <GraphObject> pagedResults = SerializationHelper.DeserializeJsonResponse <GraphObject>( Encoding.UTF8.GetString(rawResponse), objectUri); return(pagedResults); }
/// <summary> /// Gets the uri for listing the directory objects. /// </summary> /// <param name="parent">Parent object if the list is for containment type.</param> /// <param name="graphConnection">Call context.</param> /// <param name="nextLink">Link to the next set of results.</param> /// <param name="objectType">Directory object type.</param> /// <param name="filter">Filter expression generator.</param> /// <returns>Uri for listing the directory objects.</returns> /// <exception cref="UriFormatException">Invalid format for next link.</exception> /// <exception cref="ArgumentNullException">Invalid call context or object type.</exception> public static Uri GetListUri( GraphObject parent, Type objectType, GraphConnection graphConnection, string nextLink, FilterGenerator filter) { Utils.ThrowIfNullOrEmpty(graphConnection, "graphConnection"); Utils.ThrowIfNullOrEmpty(objectType, "objectType"); if (filter == null) { // Generate a dummy filter // Makes it easy to add the api-version parameter. filter = new FilterGenerator(); } // Get the entity attribute. EntityAttribute entityAttribute = Utils.GetCustomAttribute <EntityAttribute>(objectType, true); // Build a base uri for both paged and non paged queries. UriBuilder uriBuilder; string baseUri = graphConnection.AadGraphEndpoint; if (!String.IsNullOrEmpty(nextLink)) { string formattedNextLink = String.Format( CultureInfo.InvariantCulture, "{0}/{1}", baseUri, nextLink); uriBuilder = new UriBuilder(formattedNextLink); } else { if (parent != null) { baseUri = String.Format( "{0}/{1}/{2}", baseUri, Utils.GetCustomAttribute <EntityAttribute>(parent.GetType(), true).SetName, parent.ObjectId); } baseUri = String.Format( CultureInfo.InvariantCulture, "{0}/{1}", baseUri, entityAttribute.SetName); uriBuilder = new UriBuilder(baseUri); } // add the delta link to the uri uriBuilder.AddParameter(Constants.DeltaLinkQueryKeyName, graphConnection.DeltaToken); filter[Constants.QueryParameterNameApiVersion] = graphConnection.GraphApiVersion; Utils.BuildQueryFromFilter(uriBuilder, filter); return(uriBuilder.Uri); }
/// <summary> /// Deserializes a single directory object string based on the odata type. /// </summary> /// <typeparam name="T">Graph object to be deserialized into.</typeparam> /// <param name="dictionaryToken">JSON dictionary token.</param> /// <returns>Deserialized directory object.</returns> public static T DeserializeGraphObject <T>(JToken dictionaryToken, Type resultObjectType) where T : GraphObject { GraphObject graphObject = JsonConvert.DeserializeObject( dictionaryToken.ToString(), resultObjectType ?? typeof(T), new AadJsonConverter()) as GraphObject; // Make sure that every object returned is of type GraphObject. // The library does not understand any other type. Debug.Assert(graphObject != null); graphObject.TokenDictionary = dictionaryToken; graphObject.PropertiesMaterializedFromDeserialization = new List <string>(graphObject.ChangedProperties); // Clear all the properties being tracked for update. graphObject.ChangedProperties.Clear(); T returnObject = graphObject as T; if (returnObject == null) { string message = string.Format( CultureInfo.InvariantCulture, "Unexpected type {0} obtained in response. Only objects of type {1} are expected.", graphObject.GetType(), typeof(T)); throw new GraphException(message); } return(returnObject); }
/// <summary> /// Get all target values for this link (single and multi-valued) /// </summary> /// <param name="graphObject">Directory object.</param> /// <param name="linkProperty">Link property.</param> /// <returns>Paged collection of results.</returns> /// <remarks> /// This is NOT a transitive lookup, just a single level lookup. /// </remarks> public virtual IList <GraphObject> GetAllDirectLinks(GraphObject graphObject, LinkProperty linkProperty) { Utils.ValidateGraphObject(graphObject, "graphObject"); List <GraphObject> linkResults = new List <GraphObject>(); PagedResults <GraphObject> pagedResults = null; while (true) { pagedResults = this.GetLinkedObjects( graphObject, linkProperty, pagedResults == null ? null : pagedResults.PageToken, -1); linkResults.AddRange(pagedResults.Results); if (pagedResults.IsLastPage) { break; } } return(linkResults); }
public virtual PagedResults <T> ListContainments <T>( GraphObject parent, string linkToNextPage, FilterGenerator filter) where T : GraphObject { Uri requestUri; return(SerializationHelper.DeserializeJsonResponse <T>( this.ListContainmentsCore(parent, typeof(T), linkToNextPage, filter, out requestUri), requestUri)); }
public virtual PagedResults <GraphObject> ListContainments( GraphObject parent, Type containmentType, string linkToNextPage, FilterGenerator filter) { Uri requestUri; return(SerializationHelper.DeserializeJsonResponse <GraphObject>( this.ListContainmentsCore( parent, containmentType, linkToNextPage, filter, out requestUri), requestUri)); }
public virtual void Delete(GraphObject graphObject) { Utils.ValidateGraphObject(graphObject, "graphObject"); Uri deleteUri = Utils.GetRequestUri( this, graphObject.GetType(), graphObject.ObjectId); if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(HttpVerb.DELETE, true, deleteUri, null, null)); return; } this.ClientConnection.DeleteRequest(deleteUri); }
/// <summary> /// Set the deferred stream property. /// </summary> /// <param name="graphObject">Graph object.</param> /// <param name="graphProperty">Property name.</param> /// <param name="memoryStream">Memory stream.</param> /// <param name="contentType">Content type.</param> public virtual void SetStreamProperty( GraphObject graphObject, GraphProperty graphProperty, MemoryStream memoryStream, string contentType) { Utils.ValidateGraphObject(graphObject, "graphObject"); Utils.ThrowIfNullOrEmpty(memoryStream, "memoryStream"); Utils.ThrowIfNullOrEmpty(contentType, "contentType"); Uri requestUri = Utils.GetRequestUri( this, graphObject.GetType(), graphObject.ObjectId, Utils.GetPropertyName(graphProperty)); WebHeaderCollection additionalHeaders = new WebHeaderCollection(); additionalHeaders[HttpRequestHeader.ContentType] = contentType; this.ClientConnection.UploadData(requestUri, HttpVerb.PUT, memoryStream.ToArray(), additionalHeaders); }
/// <summary> /// Gets the object that needs to be sent to graph containing only updated properties. /// </summary> /// <param name="graphObject">Graph object to be enquired for changed properties.</param> /// <returns>List of key value pairs of changed property names and values.</returns> public static IDictionary <string, object> GetSerializableGraphObject(GraphObject graphObject) { Utils.ThrowIfNull(graphObject, "graphObject"); IDictionary <string, object> serializableGraphObject = new Dictionary <string, object>(graphObject.ChangedProperties.Count); foreach (string changedProperty in graphObject.ChangedProperties) { PropertyInfo propertyInfo = graphObject.GetType().GetProperty(changedProperty); JsonPropertyAttribute jsonPropertyName = Utils.GetCustomAttribute <JsonPropertyAttribute>(propertyInfo, true); serializableGraphObject.Add(jsonPropertyName.PropertyName, propertyInfo.GetValue(graphObject, null)); } return(serializableGraphObject); }
public virtual GraphObject GetContainment(GraphObject parent, Type containmentType, string containmentObjectId) { Uri listUri = Utils.GetRequestUri(this, parent.GetType(), parent.ObjectId, containmentType, containmentObjectId); if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(HttpVerb.GET, false, listUri, null, null)); return(null); } Logger.Instance.Info("Retrieving {0}", listUri); byte[] rawResponse = this.ClientConnection.DownloadData(listUri, null); PagedResults <GraphObject> pagedResults = SerializationHelper.DeserializeJsonResponse <GraphObject>( Encoding.UTF8.GetString(rawResponse), listUri); return(pagedResults.Results.FirstOrDefault()); }
private static UserProfile LoadUser(GraphObject member, GraphConnection graphConnection) { var user = member as User; if (user != null && (!user.AccountEnabled.HasValue || user.AccountEnabled.Value)) { var groups = graphConnection.GetLinkedObjects(user, LinkProperty.MemberOf, null, -1); return new UserProfile { FullName = user.DisplayName, FirstName = user.GivenName, LastName = user.Surname, UserId = user.UserPrincipalName, Manager = groups.Results.ToList() .Any(g => g.ObjectId == CloudConfigurationManager.GetSetting(Constants.ConfigurationKeys.ManagerAdGroup)) }; } return null; }
public virtual void DeleteContainment(GraphObject parent, GraphObject containment) { Utils.ThrowIfNullOrEmpty(parent, "parent"); Utils.ThrowIfNullOrEmpty(containment, "containment"); Utils.ThrowArgumentExceptionIfNullOrEmpty(parent.ObjectId, "parent.ObjectId"); Utils.ThrowArgumentExceptionIfNullOrEmpty(containment.ObjectId, "containment.ObjectId"); Uri deleteUri = Utils.GetRequestUri( this, parent.GetType(), parent.ObjectId, containment.GetType(), containment.ObjectId); if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(HttpVerb.DELETE, true, deleteUri, null, null)); return; } this.ClientConnection.DeleteRequest(deleteUri); }
/// <summary> /// Add or update the directory object on the cloud. /// </summary> /// <param name="parent">Parent object type for containment type.</param> /// <param name="containment">Containment object.</param> /// <param name="isCreate">Is this create or update?</param> /// <returns>Created base entity object.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="parent"/> or <paramref name="containment"/> is <see langword="null" /> /// </exception> private GraphObject AddOrUpdateContainment(GraphObject parent, GraphObject containment, bool isCreate) { Utils.ThrowIfNullOrEmpty(parent, "parent"); Utils.ThrowIfNullOrEmpty(containment, "containment"); containment.ValidateProperties(isCreate); Uri createUri = Utils.GetRequestUri( this, parent.GetType(), parent.ObjectId, containment.GetType(), isCreate ? String.Empty : containment.ObjectId); string requestJson = JsonConvert.SerializeObject(Utils.GetSerializableGraphObject(containment)); string methodName = isCreate ? HttpVerb.POST : HttpVerb.PATCH; if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(methodName, true, createUri, null, requestJson)); return(null); } string responseJson = this.ClientConnection.UploadString( createUri, methodName, requestJson, null, null); PagedResults <GraphObject> pagedResults = SerializationHelper.DeserializeJsonResponse <GraphObject>(responseJson, createUri); if (pagedResults == null || pagedResults.Results == null || pagedResults.Results.Count != 1) { throw new InvalidOperationException("Unable to deserialize the response"); } containment.ChangedProperties.Clear(); pagedResults.Results[0].ChangedProperties.Clear(); return(pagedResults.Results[0]); }
/// <summary> /// List the containment objects of the given type /// </summary> /// <param name="parent">Parent object type for containment type.</param> /// <param name="containmentType">Containment object type.</param> /// <param name="linkToNextPage">Directory object type.</param> /// <param name="filter">OData filter.</param> /// <param name="listUri">Set to the request uri.</param> /// <returns>Paged collection of results.</returns> private string ListContainmentsCore( GraphObject parent, Type containmentType, string linkToNextPage, FilterGenerator filter, out Uri listUri) { listUri = Utils.GetListUri(parent, containmentType, this, linkToNextPage, filter); if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(HttpVerb.GET, false, listUri, null, null)); return(null); } Logger.Instance.Info("Retrieving {0}", listUri); byte[] rawResponse = this.ClientConnection.DownloadData(listUri, null); if (rawResponse == null) { return(null); } return(Encoding.UTF8.GetString(rawResponse)); }
/// <summary> /// Get the deferred stream property. /// </summary> /// <param name="graphObject">Graph object.</param> /// <param name="graphProperty">Property name.</param> /// <returns>Memory stream for the byte buffer.</returns> /// <param name="acceptType">Accept type header value.</param> public virtual Stream GetStreamProperty( GraphObject graphObject, GraphProperty graphProperty, string acceptType) { Utils.ValidateGraphObject(graphObject, "graphObject"); Utils.ThrowIfNullOrEmpty(acceptType, "acceptType"); Uri requestUri = Utils.GetRequestUri( this, graphObject.GetType(), graphObject.ObjectId, Utils.GetPropertyName(graphProperty)); WebHeaderCollection additionalHeaders = new WebHeaderCollection(); additionalHeaders[HttpRequestHeader.ContentType] = acceptType; byte[] buffer = this.ClientConnection.DownloadData(requestUri, additionalHeaders); if (buffer != null) { return(new MemoryStream(buffer)); } return(new MemoryStream()); }
public virtual void DeleteLink( GraphObject sourceObject, GraphObject targetObject, LinkProperty linkProperty) { Utils.ValidateGraphObject(sourceObject, "sourceObject"); Uri deleteUri; bool isSingleValued = Utils.GetLinkAttribute(sourceObject.GetType(), linkProperty).IsSingleValued; if (isSingleValued) { // If the link is single valued, the target object id should not be part of the Uri. deleteUri = Utils.GetRequestUri( this, sourceObject.GetType(), sourceObject.ObjectId, Constants.LinksFragment, Utils.GetLinkName(linkProperty)); } else { Utils.ValidateGraphObject(targetObject, "targetObject"); deleteUri = Utils.GetRequestUri( this, sourceObject.GetType(), sourceObject.ObjectId, Constants.LinksFragment, Utils.GetLinkName(linkProperty), targetObject.ObjectId); } if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(HttpVerb.DELETE, true, deleteUri, null, null)); return; } this.ClientConnection.DeleteRequest(deleteUri); }
/// <summary> /// Serialize the object into JSON. /// </summary> /// <param name="writer">JSON writer.</param> /// <param name="value">PropertyValue to be serialized.</param> /// <param name="serializer">JSON serializer.</param> public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { return; } ChangeTrackingCollection <GraphObject> graphObjects = value as ChangeTrackingCollection <GraphObject>; if (graphObjects == null) { if (!(value is IEnumerable)) { throw new ArgumentException("parameter 'value' is not of type IEnumerable."); } graphObjects = new ChangeTrackingCollection <GraphObject>(); IEnumerable iEnumerableValue = value as IEnumerable; foreach (object valueObject in iEnumerableValue) { GraphObject graphObject = valueObject as GraphObject; if (graphObject == null) { throw new ArgumentException( "Each value in the ChangeTrackingCollection should be of type GraphObject."); } graphObjects.Add(graphObject); } } if (graphObjects.Count > 0) { throw new ArgumentException("Updating links is not supported from entity."); } writer.WriteNull(); }
public virtual void AddLink( GraphObject sourceObject, GraphObject targetObject, LinkProperty linkProperty) { Utils.ValidateGraphObject(sourceObject, "sourceObject"); Utils.ValidateGraphObject(targetObject, "targetObject"); Uri linkUri = Utils.GetRequestUri( this, sourceObject.GetType(), sourceObject.ObjectId, Constants.LinksFragment, Utils.GetLinkName(linkProperty)); Uri targetObjectUri = Utils.GetRequestUri( this, targetObject.GetType(), targetObject.ObjectId); Dictionary <string, string> postParameters = new Dictionary <string, string>() { { "url", targetObjectUri.ToString() } }; string requestJson = JsonConvert.SerializeObject(postParameters); bool isSingleValued = Utils.GetLinkAttribute(sourceObject.GetType(), linkProperty).IsSingleValued; string methodName = isSingleValued ? HttpVerb.PUT : HttpVerb.POST; if (this.returnBatchItem.Value) { this.batchRequestItems.Value.Add(new BatchRequestItem(methodName, true, linkUri, null, requestJson)); return; } this.ClientConnection.UploadString( linkUri, methodName, requestJson, null, null); }
/// <summary> /// Returns the groups that the <see cref="DirectoryObject"/> is a member of, among the groups /// requested. /// </summary> /// <param name="directoryObject">Object whose membership needs to be checked.</param> /// <param name="groupIds">Group ids.</param> /// <returns> /// List of groups that the object is a part of (from the list of groupIds provided) /// </returns> public virtual IList<string> CheckMemberGroups(GraphObject graphObject, IList<string> groupIds) { Utils.ValidateGraphObject(graphObject, "graphObject"); Utils.ThrowIfNullOrEmpty(groupIds, "groupIds"); List<string> memberGroups = new List<string>(); Uri requestUri = Utils.GetRequestUri<DirectoryObject>( this, graphObject.ObjectId, Constants.ActionCheckMemberGroups); Logger.Instance.Info("POSTing to {0}", requestUri); Dictionary<string, IList<string>> parameters = new Dictionary<string, IList<string>>(); parameters["groupIds"] = groupIds; string requestJson = JsonConvert.SerializeObject(parameters); string responseJson = this.ClientConnection.UploadString( requestUri, HttpVerb.POST, requestJson, null, null); PagedResults<GraphObject> pagedResults = SerializationHelper.DeserializeJsonResponse<GraphObject>(responseJson, requestUri); memberGroups.AddRange(pagedResults.MixedResults); return memberGroups; }
/// <summary> /// Validate that the graph object is not null and has a valid objectid. /// </summary> /// <param name="graphObject">Graph object.</param> /// <param name="parameterName">Name of the parameter, will be quoted in the message.</param> /// <exception cref="ArgumentNullException">Graph object is null.</exception> /// <exception cref="ArgumentException">If the graph object is invalid.</exception> public static void ValidateGraphObject(GraphObject graphObject, string parameterName) { Utils.ThrowIfNullOrEmpty(graphObject, parameterName); Utils.ThrowArgumentExceptionIfNullOrEmpty(graphObject.ObjectId, parameterName); }
public virtual GraphObject Add(GraphObject entity) { return(this.AddOrUpdate(entity, true)); }
public virtual GraphObject Update(GraphObject entity) { return(this.AddOrUpdate(entity, false)); }
public GraphObject AddContainment(GraphObject parent, GraphObject containment) { return(this.AddOrUpdateContainment(parent, containment, true)); }
public T UpdateContainment <T>(GraphObject parent, T containment) where T : GraphObject { return(this.AddOrUpdateContainment(parent, containment, false) as T); }
/// <summary> /// Read JSON string to the object. /// </summary> /// <param name="reader">JSON reader.</param> /// <param name="objectType">Object type.</param> /// <param name="existingValue">Existing value.</param> /// <param name="serializer">Json serializer</param> /// <returns>Deserialized object.</returns> /// <remarks> /// 1. Check if this is an array or a single element. /// If Array, deserialize each element as DirectoryObject and return the list /// 2. Deserialize using the default property set /// 3. Find the non-deserialized properties and add them to the Dictionary. /// </remarks> public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartArray) { JToken jsonToken = JArray.ReadFrom(reader); List <JToken> jsonTokens = jsonToken.ToList(); // This converter can only handle an array of graph objects. // Not native types. When deserializing an expanded link, all linked objects will be // deserialized as GraphObject. ChangeTrackingCollection <GraphObject> resultObjects = new ChangeTrackingCollection <GraphObject>(); AadJsonConverter jsonConverter = new AadJsonConverter(); foreach (JToken arrayToken in jsonTokens) { GraphObject resultElement = JsonConvert.DeserializeObject( arrayToken.ToString(), typeof(GraphObject), jsonConverter) as GraphObject; resultObjects.Add(resultElement); } return(resultObjects); } // Load the JSON into a JsonObject so that we can inspect the odata.type property. Object resultObject; JObject jsonObject = JObject.Load(reader); List <JProperty> jsonProperties = jsonObject.Properties().ToList(); JProperty odataTypeProperty = jsonProperties.FirstOrDefault(x => x.Name == Constants.OdataTypeKey); // If there is odata.type value, use that to find the type to be deserialized into. // If not, use the type that was passed to the de-serializer. Type resultObjectType; if (odataTypeProperty != null && SerializationHelper.TryGetImplementationForAadType( odataTypeProperty.Value.ToString(), out resultObjectType) && typeof(GraphObject).IsAssignableFrom(resultObjectType)) { resultObject = Activator.CreateInstance(resultObjectType) as GraphObject; } else { resultObjectType = objectType; resultObject = Activator.CreateInstance(resultObjectType); } // Deserialize all known properties using the default JSON.NET serializer resultObject = JsonConvert.DeserializeObject(jsonObject.ToString(), resultObjectType); // TODO: If the odata type is null, should still try to deserialize additional values using // the graphObjectType. GraphObject graphObject = resultObject as GraphObject; if (graphObject != null && odataTypeProperty != null) { Dictionary <string, PropertyInfo> propertyNameToInfoMap = this.GetPropertyInfosForAadType(odataTypeProperty.Value.ToString(), resultObjectType); foreach (JProperty jsonProperty in jsonProperties) { PropertyInfo propertyInfo; if (!propertyNameToInfoMap.TryGetValue(jsonProperty.Name, out propertyInfo)) { graphObject.NonSerializedProperties[jsonProperty.Name] = jsonProperty.Value.ToString(); } } } return(graphObject); }
public virtual PagedResults <GraphObject> GetLinkedObjects( GraphObject graphObject, LinkProperty linkProperty, string nextPageToken) { return(this.GetLinkedObjects(graphObject, linkProperty, nextPageToken, -1)); }
public virtual T GetContainment <T>(GraphObject parent, string containmentObjectId) where T : GraphObject { return(this.GetContainment(parent, typeof(T), containmentObjectId) as T); }