public async Task setting_default_scopes_impact_new_users()
        {
            var user    = TestHelper.StObjMap.StObjs.Obtain <UserTable>();
            var p       = TestHelper.StObjMap.StObjs.Obtain <Package>();
            var factory = TestHelper.StObjMap.StObjs.Obtain <IPocoFactory <IUserGitLabInfo> >();

            using (var ctx = new SqlStandardCallContext())
            {
                AuthScopeSet original = await p.ReadDefaultScopeSetAsync(ctx);

                original.Contains("nimp").Should().BeFalse();
                original.Contains("thing").Should().BeFalse();
                original.Contains("other").Should().BeFalse();

                {
                    int id = await user.CreateUserAsync(ctx, 1, Guid.NewGuid().ToString());

                    IUserGitLabInfo userInfo = factory.Create();
                    userInfo.GitLabAccountId = Guid.NewGuid().ToString();
                    await p.UserGitLabTable.CreateOrUpdateGitLabUserAsync(ctx, 1, id, userInfo);

                    var info = await p.UserGitLabTable.FindKnownUserInfoAsync(ctx, userInfo.GitLabAccountId);

                    AuthScopeSet userSet = await p.ReadScopeSetAsync(ctx, info.UserId);

                    userSet.ToString().Should().Be(original.ToString());
                }
                AuthScopeSet replaced = original.Clone();
                replaced.Add(new AuthScopeItem("nimp"));
                replaced.Add(new AuthScopeItem("thing", ScopeWARStatus.Rejected));
                replaced.Add(new AuthScopeItem("other", ScopeWARStatus.Accepted));
                await p.AuthScopeSetTable.SetScopesAsync(ctx, 1, replaced);

                var readback = await p.ReadDefaultScopeSetAsync(ctx);

                readback.ToString().Should().Be(replaced.ToString());
                // Default scopes have non W status!
                // This must not impact new users: their satus must always be be W.
                readback.ToString().Should().Contain("[R]thing")
                .And.Contain("[A]other");

                {
                    int id = await user.CreateUserAsync(ctx, 1, Guid.NewGuid().ToString());

                    IUserGitLabInfo userInfo = p.UserGitLabTable.CreateUserInfo <IUserGitLabInfo>();
                    userInfo.GitLabAccountId = Guid.NewGuid().ToString();
                    await p.UserGitLabTable.CreateOrUpdateGitLabUserAsync(ctx, 1, id, userInfo, UCLMode.CreateOnly | UCLMode.UpdateOnly);

                    userInfo = (IUserGitLabInfo)(await p.UserGitLabTable.FindKnownUserInfoAsync(ctx, userInfo.GitLabAccountId)).Info;
                    AuthScopeSet userSet = await p.ReadScopeSetAsync(ctx, id);

                    userSet.ToString().Should().Contain("[W]thing")
                    .And.Contain("[W]other")
                    .And.Contain("[W]nimp");
                }
                await p.AuthScopeSetTable.SetScopesAsync(ctx, 1, original);
            }
        }
        /// <summary>
        /// Challenges <see cref="IUserGitLabInfo"/> data to identify a user.
        /// Note that a successful challenge may have side effects such as updating claims, access tokens or other data
        /// related to the user and this provider.
        /// </summary>
        /// <param name="ctx">The call context to use.</param>
        /// <param name="info">The payload to challenge.</param>
        /// <param name="actualLogin">Set it to false to avoid login side-effect (such as updating the LastLoginTime) on success.</param>
        /// <returns>The login result.</returns>
        public LoginResult LoginUser(ISqlCallContext ctx, IUserGitLabInfo info, bool actualLogin = true)
        {
            var mode = actualLogin
                        ? UCLMode.UpdateOnly | UCLMode.WithActualLogin
                        : UCLMode.UpdateOnly | UCLMode.WithCheckLogin;
            var r = UserGitLabUCL(ctx, 1, 0, info, mode);

            return(r.LoginResult);
        }
 protected abstract UCLResult UserGitLabUCL(
     ISqlCallContext ctx,
     int actorId,
     int userId,
     [ParameterSource] IUserGitLabInfo info,
     UCLMode mode);
 /// <summary>
 /// Creates or updates a user entry for this provider.
 /// This is the "binding account" feature since it binds an external identity to
 /// an already existing user that may already be registered into other authencation providers.
 /// </summary>
 /// <param name="ctx">The call context to use.</param>
 /// <param name="actorId">The acting actor identifier.</param>
 /// <param name="userId">The user identifier that must be registered.</param>
 /// <param name="info">Provider specific data: the <see cref="IUserGitLabInfo"/> poco.</param>
 /// <param name="mode">Optionnaly configures Create, Update only or WithLogin behavior.</param>
 /// <returns>The result.</returns>
 public UCLResult CreateOrUpdateGitLabUser(ISqlCallContext ctx, int actorId, int userId, IUserGitLabInfo info, UCLMode mode = UCLMode.CreateOrUpdate)
 {
     return(UserGitLabUCL(ctx, actorId, userId, info, mode));
 }