Ejemplo n.º 1
0
 /// <summary>
 /// Called when a profile requests user authorization
 /// </summary>
 /// <param name="authenticating_instance">Authenticating instance</param>
 /// <param name="e"><see cref="RequestAuthorization"/> event arguments</param>
 public void OnRequestAuthorization(Instance authenticating_instance, RequestAuthorizationEventArgs e)
 {
     RequestAuthorization?.Invoke(authenticating_instance, e);
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets instance profile list available to the user
        /// </summary>
        /// <param name="authenticating_instance">Authenticating instance (can be same as this instance)</param>
        /// <param name="ct">The token to monitor for cancellation requests</param>
        /// <returns>Profile list</returns>
        public ObservableCollection <Profile> GetProfileList(Instance authenticating_instance, CancellationToken ct = default(CancellationToken))
        {
            lock (_profile_list_lock)
            {
                if (_profile_list == null)
                {
                    // Get API endpoints.
                    var api = GetEndpoints(ct);
                    var e   = new RequestAuthorizationEventArgs("config");

retry:
                    // Request authentication token.
                    OnRequestAuthorization(authenticating_instance, e);
                    if (e.AccessToken == null)
                    {
                        throw new AccessTokenNullException();
                    }

                    try
                    {
                        // Get and load profile list.
                        var profile_list = new ObservableCollection <Profile>();
                        profile_list.LoadJSONAPIResponse(Xml.Response.Get(
                                                             uri: api.ProfileList,
                                                             token: e.AccessToken,
                                                             ct: ct).Value, "profile_list", ct);

                        foreach (var profile in profile_list)
                        {
                            // Bind profile to our instance.
                            profile.Instance = this;

                            // Attach to RequestAuthorization profile events.
                            profile.RequestAuthorization += (object sender_profile, RequestAuthorizationEventArgs e_profile) => OnRequestAuthorization(authenticating_instance, e_profile);
                        }

                        // If we got here, save the profile list.
                        _profile_list = profile_list;
                    }
                    catch (OperationCanceledException) { throw; }
                    catch (WebException ex)
                    {
                        if (ex.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            // Access token was rejected (401 Unauthorized).
                            if (e.TokenOrigin == RequestAuthorizationEventArgs.TokenOriginType.Saved)
                            {
                                // Access token loaded from the settings was rejected.
                                // This might happen when ill-clocked client thinks the token is still valid, but the server expired it already.
                                // Retry with forced access token refresh.
                                e.ForceRefresh = true;
                            }
                            else
                            {
                                // Retry with forced authorization, ignoring saved access token completely.
                                e.SourcePolicy = RequestAuthorizationEventArgs.SourcePolicyType.ForceAuthorization;
                            }
                            goto retry;
                        }
                        else
                        {
                            throw new AggregateException(Resources.Strings.ErrorProfileListLoad, ex);
                        }
                    }
Ejemplo n.º 3
0
        /// <summary>
        /// Gets server profile list available to the user
        /// </summary>
        /// <param name="authenticatingServer">Authenticating server (can be same as this server)</param>
        /// <param name="ct">The token to monitor for cancellation requests</param>
        /// <returns>Profile list</returns>
        public ObservableCollection <Profile> GetProfileList(Server authenticatingServer, CancellationToken ct = default)
        {
            lock (ProfilesLock)
            {
                if (Profiles != null)
                {
                    return(Profiles);
                }

                // Get API endpoints.
                var api = GetEndpoints(ct);
                var e   = new RequestAuthorizationEventArgs("config");

retry:
                // Request authentication token.
                OnRequestAuthorization(authenticatingServer, e);

                try
                {
                    // Parse JSON string and get inner key/value dictionary.
                    Trace.TraceInformation("Loading info {0}", api.Info);
                    var obj = eduJSON.Parser.GetValue <Dictionary <string, object> >(
                        (Dictionary <string, object>)eduJSON.Parser.Parse(Xml.Response.Get(
                                                                              uri: api.Info,
                                                                              token: e.AccessToken,
                                                                              ct: ct).Value, ct),
                        "info");

                    // Load collection.
                    if (!eduJSON.Parser.GetValue(obj, "profile_list", out List <object> obj2))
                    {
                        throw new eduJSON.InvalidParameterTypeException(nameof(obj2), typeof(Dictionary <string, object>), obj.GetType());
                    }

                    // Parse all items listed. Don't do it in parallel to preserve the sort order.
                    var profileList = new ObservableCollection <Profile>();
                    foreach (var el in obj2)
                    {
                        var profile = new Profile(this);
                        profile.Load(el);

                        // Attach to RequestAuthorization profile events.
                        profile.RequestAuthorization += (object sender_profile, RequestAuthorizationEventArgs e_profile) => OnRequestAuthorization(authenticatingServer, e_profile);

                        profileList.Add(profile);
                    }
                    return(Profiles = profileList);
                }
                catch (OperationCanceledException) { throw; }
                catch (WebException ex)
                {
                    if (ex.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        // Access token was rejected (401 Unauthorized).
                        if (e.TokenOrigin == RequestAuthorizationEventArgs.TokenOriginType.Saved)
                        {
                            // Access token loaded from the settings was rejected.
                            // This might happen when ill-clocked client thinks the token is still valid, but the server expired it already.
                            // Or the token was revoked on the server side.
                            // Retry with forced access token refresh.
                            e.SourcePolicy = RequestAuthorizationEventArgs.SourcePolicyType.ForceAuthorization;
                            goto retry;
                        }
                    }
                    if (ex is WebExceptionEx exEx && ex.Response.ContentType == "application/json")
                    {
                        var obj = (Dictionary <string, object>)eduJSON.Parser.Parse(exEx.ResponseText, ct);
                        throw new AggregateException(Resources.Strings.ErrorProfileListLoad + "\n" + eduJSON.Parser.GetValue <string>(obj, "error"), ex);
                    }
                    throw new AggregateException(Resources.Strings.ErrorProfileListLoad, ex);
                }
                catch (Exception ex) { throw new AggregateException(Resources.Strings.ErrorProfileListLoad, ex); }
            }
        }