public async Task <ActionResult <ApiResult <SessionPreview> > > MfaDisable([FromBody] MfaDisableModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null || !await this.Password.ValidatePasswordHashAsync(data.Password, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var mfa = await this.MfaRepository.GetMfaSettingsAsync(user.Id, cancellationToken); if (mfa == null || !mfa.IsConfirmed) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "MFA is not configured.")))); } if (data.MfaCode.Length == 6 && !this.MfaValidator.ValidateCode(data.MfaCode, mfa) || data.MfaCode.Length == 8 && !this.MfaValidator.ValidateRecoveryCode(data.MfaCode, mfa)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Invalid MFA code provided.")))); } await this.MfaRepository.RemoveMfaAsync(user.Id, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
public async Task <ActionResult <ApiResult <MfaSettingsModel> > > StartMfaEnable([FromBody] UserSudoModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null || !await this.Password.ValidatePasswordHashAsync(data.Password, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var mfa = await this.MfaRepository.GetMfaSettingsAsync(user.Id, cancellationToken); if (mfa != null && mfa.IsConfirmed) { return(this.StatusCode(400, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.AlreadyConfigured, "MFA is already configured.")))); } var tkpair = this.ActionTokenPairHandler.IssueTokenPair(TokenActionMFAConfigure); var stateId = await this.MfaStateRepository.GenerateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), tkpair.Server, cancellationToken); var state = this.PackState(stateId, tkpair.Client); mfa = await this.MfaValidator.GenerateMfaAsync(this.MfaRepository, user.Id, false, cancellationToken); var rmfa = this.MfaValidator.GenerateClientData(mfa, user.Username, this.EventConfiguration.Name, state); return(this.Ok(ApiResult.FromResult(rmfa))); }
public async Task <ActionResult <ApiResult <TeamPreview> > > Invite(long userId, CancellationToken cancellationToken = default) { var tuser = await this.UserRepository.GetUserAsync(userId, cancellationToken); if (tuser == null) { return(this.NotFound(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.UserNotFound, "Specified user does not exist.")))); } if (!tuser.IsAuthorized) { return(this.StatusCode(403, ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.MissingPermissions, "User is not allowed to participate.")))); } if (tuser.Team != null) { return(this.StatusCode(403, ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.UserAlreadyOnTeam, "Specified user already has a team.")))); } await this.UserRepository.CreateTeamInviteAsync(tuser.Id, this.RosettaUser.Team.Id, cancellationToken); var rteam = this.UserPreviewRepository.GetTeam(this.RosettaUser.Team); return(this.Ok(ApiResult.FromResult(rteam))); }
/// <summary> /// Returns the object of a custom request with a provided endpoint. /// </summary> /// <typeparam name="T">The type that this request will be cast to.</typeparam> /// <param name="endpoint">The endpoint that will be appended to the base URL for this call.</param> /// <returns>An object of type T from the specified URL.</returns> protected async Task <T> GetAsync <T>(string endpoint) { HttpResponseMessage response = await HttpClient.GetAsync($"{DblApi.BaseUrl}{endpoint}"); ApiResult <T> result; try { result = response.IsSuccessStatusCode ? ApiResult <T> .FromSuccess(JsonConvert.DeserializeObject <T>(await response.Content.ReadAsStringAsync())) : ApiResult <T> .FromHttpError(response.StatusCode); } catch (Exception ex) { result = ApiResult <T> .FromError(ex); } if (!result.IsSuccess) { throw new Exception(result.ErrorReason); } if (result.Value == null) { return(default);
public async Task <ActionResult <ApiResult <IEnumerable <ScoreboardEntryPreview> > > > GetTeamSolves(long id, CancellationToken cancellationToken = default) { var team = await this.UserRepository.GetTeamAsync(id); if (team == null) { return(this.NotFound(ApiResult.FromError <IEnumerable <ScoreboardEntryPreview> >(new ApiError(ApiErrorCode.TeamNotFound, "Specified team does not exist.")))); } var solves = await this.ChallengeRepository.GetSuccessfulSolvesAsync(id, cancellationToken); var challengeIds = solves.Select(x => x.Challenge.Id); var scores = await this.ChallengeCacheRepository.GetScoresAsync(challengeIds, cancellationToken); var rteam = this.UserPreviewRepository.GetTeam(team); var rusers = team.Id == this.RosettaUser.Team.Id ? solves.Select(x => x.User) .Distinct() .ToDictionary(x => x.Id, x => this.UserPreviewRepository.GetUser(x)) : null; var scoreboard = this.ChallengePreviewRepository.GetScoreboard(solves, scores, this.StartTime, rusers); return(this.Ok(ApiResult.FromResult(scoreboard))); }
public async Task <ActionResult <ApiResult <SessionPreview> > > LoginMfa([FromBody] MfaLoginModel data, CancellationToken cancellationToken = default) { if (data.ActionToken == null || data.MfaCode == null) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "MFA state validation failed.")))); } var(stateId, clientTk) = this.UnpackState(data.ActionToken); var serverTk = await this.MfaStateRepository.ValidateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), stateId, cancellationToken); var tokenPair = new ActionTokenPair(clientTk, serverTk); if (!this.ActionTokenPairHandler.ValidateTokenPair(tokenPair, TokenActionMFA)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "MFA state validation failed.")))); } var userId = BinaryPrimitives.ReadInt64BigEndian(clientTk.State); var mfa = await this.MfaRepository.GetMfaSettingsAsync(userId, cancellationToken); if (mfa == null || !mfa.IsConfirmed) { return(this.StatusCode(400, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "MFA not configured.")))); } if (data.MfaCode.Length == 6) { if (!this.MfaValidator.ValidateCode(data.MfaCode, mfa)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Invalid MFA code provided.")))); } } else if (data.MfaCode.Length == 8) { if (!this.MfaValidator.ValidateRecoveryCode(data.MfaCode, mfa)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Invalid MFA code provided.")))); } await this.MfaRepository.TripRecoveryCodeAsync(userId, cancellationToken); } else { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Invalid MFA code provided.")))); } var user = await this.UserRepository.GetUserAsync(userId, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
private async Task <ApiResult> TryRequest(ApiRequest request, Func <Task <HttpResponseMessage> > requestFunction) { try { var responseMessage = await requestFunction().ConfigureAwait(false); return(ApiResult.FromResponse(request, new ApiResponse(_serializer, responseMessage))); } catch (HttpRequestException ex) { return(await Task.FromResult(ApiResult.FromError(request, ex)).ConfigureAwait(false)); } }
public async Task <ActionResult <ApiResult <TeamPreview> > > Create([FromBody] TeamCreateModel teamCreate, CancellationToken cancellationToken = default) { var team = await this.UserRepository.CreateTeamAsync(teamCreate.Name, cancellationToken); if (team == null) { return(this.Conflict(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.DuplicateTeamName, "A team with given name already exists.")))); } await this.UserRepository.AssignTeamMembershipAsync(this.RosettaUser.Id, team.Id, cancellationToken); var rteam = this.UserPreviewRepository.GetTeam(team); return(this.StatusCode(201, ApiResult.FromResult(rteam))); }
public async Task <ActionResult <ApiResult <bool> > > Register([FromBody] UserRegistrationModel data, CancellationToken cancellationToken = default) { var pwd = await this.Password.CreatePasswordHashAsync(data.Password); var user = await this.UserRepository.CreateUserAsync(data.Username, true, cancellationToken); if (user == null) { return(this.Conflict(ApiResult.FromError <bool>(new ApiError(ApiErrorCode.DuplicateUsername, "A user with given name already exists.")))); } await this.UserRepository.UpdateUserPasswordAsync(user.Id, pwd, cancellationToken); return(this.Ok(ApiResult.FromResult(true))); }
public async Task <ActionResult <ApiResult <SessionPreview> > > UpdateUserCountry([FromBody] UserCountryModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; user = await this.UserRepository.UpdateUserCountryAsync(user.Id, data.Code, cancellationToken); if (user == null) { return(this.BadRequest(ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidName, "Invalid country name specified.")))); } var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
public Task OnAuthorizationAsync(AuthorizationFilterContext context) { var eventCfg = this.CtfConfigurationLoader.LoadEventData(); var start = eventCfg.EndTime - DateTimeOffset.UtcNow; if (start < TimeSpan.Zero) { context.Result = new ObjectResult(ApiResult.FromError <object>(new ApiError(ApiErrorCode.Unauthorized, "Event has concluded."))) { StatusCode = 403 } } ; return(Task.CompletedTask); } }
public void FromError_ShouldInitializePropertiesCorrect() { // arrange var expectedRequest = ApiRequest.To(string.Empty); var expectedException = new HttpRequestException(); // act var result = ApiResult.FromError(expectedRequest, expectedException); // assert Assert.Equal(expectedRequest, result.Request); Assert.Equal(expectedException, result.Exception); Assert.Throws <InvalidOperationException>(() => result.Response); Assert.Equal(ResultState.RequestError, result.State); Assert.True(result.IsRequestError); Assert.False(result.IsSuccess); }
public Task OnAuthorizationAsync(AuthorizationFilterContext context) { var eventCfg = this.CtfConfigurationLoader.LoadEventData(); var start = DateTimeOffset.UtcNow - eventCfg.StartTime; if (start >= TimeSpan.Zero) { context.Result = new ObjectResult(ApiResult.FromError <object>(new ApiError(ApiErrorCode.EventStarted, "Event has already started. Team compositions are locked."))) { StatusCode = 403 } } ; return(Task.CompletedTask); } }
public async Task <ActionResult <ApiResult <SessionPreview> > > MfaEnable([FromBody] MfaLoginModel data, CancellationToken cancellationToken = default) { var(stateId, clientTk) = this.UnpackState(data.ActionToken); var serverTk = await this.MfaStateRepository.ValidateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), stateId, cancellationToken); var tokenPair = new ActionTokenPair(clientTk, serverTk); if (!this.ActionTokenPairHandler.ValidateTokenPair(tokenPair, TokenActionMFAConfigure)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "MFA state validation failed.")))); } var user = this.RosettaUser; var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var mfa = await this.MfaRepository.GetMfaSettingsAsync(user.Id, cancellationToken); if (mfa == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "MFA not configured.")))); } if (mfa.IsConfirmed) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.AlreadyConfigured, "MFA is already configured.")))); } if (!this.MfaValidator.ValidateCode(data.MfaCode, mfa)) { await this.MfaRepository.RemoveMfaAsync(user.Id, cancellationToken); return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Invalid MFA code provided.")))); } await this.MfaRepository.ConfirmMfaAsync(user.Id, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
/// <summary> /// Gets and parses objects /// </summary> /// <typeparam name="T">Type to parse to</typeparam> /// <param name="url">Url to get from</param> /// <returns>Object of type T</returns> protected async Task <T> GetAsync <T>(string url) { HttpResponseMessage t = await _httpClient.GetAsync(baseEndpoint + url); ApiResult <T> result; try { result = t.IsSuccessStatusCode ? ApiResult <T> .FromSuccess(JsonSerializer.Deserialize <T>(await t.Content.ReadAsStringAsync())) : ApiResult <T> .FromHttpError(t.StatusCode); } catch (Exception ex) { result = ApiResult <T> .FromError(ex); } return(result.Value); }
public async Task <ActionResult <ApiResult <string> > > Endpoint(string provider, CancellationToken cancellationToken = default) { var oauth = this.OAuthSelector.GetById(provider); if (oauth == null) { return(this.NotFound(ApiResult.FromError <string>(new ApiError(ApiErrorCode.InvalidProvider, "Specified provider does not exist.")))); } var tkpair = this.ActionTokenPairHandler.IssueTokenPair(TokenActionOAuth); var stateId = await this.OAuthStateRepository.GenerateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), tkpair.Server, cancellationToken); var clientToken = tkpair.Client; var state = this.PackState(stateId, clientToken); return(this.Ok(ApiResult.FromResult(oauth.GetAuthenticationUrl(this.CreateContext(provider, state))))); }
public async Task <ActionResult <ApiResult <TeamPreview> > > AcceptInvite(long teamId, CancellationToken cancellationToken = default) { var invite = await this.UserRepository.GetTeamInviteAsync(this.RosettaUser.Id, teamId, cancellationToken); if (invite == null) { return(this.NotFound(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.Unauthorized, "You were not invited to that team.")))); } await this.UserRepository.AssignTeamMembershipAsync(this.RosettaUser.Id, invite.Team.Id, cancellationToken); await this.UserRepository.ClearTeamInvitesAsync(this.RosettaUser.Id, cancellationToken); var team = await this.UserRepository.GetTeamAsync(invite.Team.Id); var rteam = this.UserPreviewRepository.GetTeam(team); return(this.Ok(ApiResult.FromResult(rteam))); }
public Task OnAuthorizationAsync(AuthorizationFilterContext context) { var eventCfg = this.CtfConfigurationLoader.LoadEventData(); var elapsed = DateTimeOffset.UtcNow - eventCfg.StartTime; if (elapsed < TimeSpan.Zero) { context.Result = new ObjectResult(ApiResult.FromError <object>(new ApiError(ApiErrorCode.Unauthorized, "Event has not yet started."))) { StatusCode = 403 } } ; context.HttpContext.Items["RosettaCTF:StartElapsed"] = elapsed; context.HttpContext.Items["RosettaCTF:StartTime"] = eventCfg.StartTime; return(Task.CompletedTask); } }
private async Task RunHandlerAsync(HttpContext ctx) { ctx.Response.ContentType = "application/json"; ApiError error; var exhpf = ctx.Features.Get <IExceptionHandlerPathFeature>(); if (exhpf?.Error != null) { ctx.Response.StatusCode = 500; error = new ApiError(ApiErrorCode.GenericError, "Internal server error occured while processing the request."); } else { error = new ApiError(ApiErrorCode.GenericError, $"HTTP Error {ctx.Response.StatusCode}."); } await JsonSerializer.SerializeAsync(ctx.Response.Body, ApiResult.FromError <object>(error), AbstractionUtilities.DefaultJsonOptions); }
public async Task <ActionResult <ApiResult <IEnumerable <string> > > > MfaGetBackups([FromBody] UserSudoModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null || !await this.Password.ValidatePasswordHashAsync(data.Password, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var mfa = await this.MfaRepository.GetMfaSettingsAsync(user.Id, cancellationToken); if (mfa == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "MFA not configured.")))); } var codes = this.MfaValidator.GenerateRecoveryCodes(mfa); return(this.Ok(ApiResult.FromResult(codes))); }
public async Task <ActionResult <ApiResult <TeamPreview> > > Kick(long userId, CancellationToken cancellationToken = default) { if (DateTimeOffset.UtcNow >= this.EventConfiguration.StartTime) { return(this.StatusCode(403, ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.EventStarted, "Cannot modify team composition after the event has started.")))); } var tuser = await this.UserRepository.GetUserAsync(userId, cancellationToken); if (tuser == null) { return(this.NotFound(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.UserNotFound, "Specified user does not exist.")))); } if (tuser.Team == null || tuser.Team.Id != this.RosettaUser.Team.Id) { return(this.NotFound(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.UserNotFound, "Specified user is not part of this team.")))); } var teamId = tuser.Team.Id; await this.UserRepository.AssignTeamMembershipAsync(tuser.Id, null, cancellationToken); var team = await this.UserRepository.GetTeamAsync(teamId); if (!team.Members.Any()) { await this.UserRepository.DeleteTeamAsync(teamId); } if (this.RosettaUser.Id != tuser.Id) { var rteam = this.UserPreviewRepository.GetTeam(team); return(this.Ok(ApiResult.FromResult(rteam))); } else { return(this.Ok(ApiResult.FromResult <TeamPreview>(null))); } }
public async Task <ActionResult <ApiResult <TeamPreview> > > Get(long?id = null, CancellationToken cancellationToken = default) { ITeam team; if (id == null) { team = this.RosettaUser?.Team; } else { team = await this.UserRepository.GetTeamAsync(id.Value); } if (team == null) { return(this.NotFound(ApiResult.FromError <TeamPreview>(new ApiError(ApiErrorCode.TeamNotFound, "Specified team does not exist.")))); } var rteam = this.UserPreviewRepository.GetTeam(team); return(this.Ok(ApiResult.FromResult(rteam))); }
public async Task <ActionResult <ApiResult <SessionPreview> > > Login([FromBody] UserLoginModel data, CancellationToken cancellationToken = default) { var user = await this.UserRepository.GetUserAsync(data.Username, cancellationToken); if (user == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } if (!await this.Password.ValidatePasswordHashAsync(data.Password, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } if (user.RequiresMfa) { var mfaState = new byte[8]; BinaryPrimitives.WriteInt64BigEndian(mfaState, user.Id); var tokenPair = this.ActionTokenPairHandler.IssueTokenPair(TokenActionMFA, mfaState); var stateId = await this.MfaStateRepository.GenerateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), tokenPair.Server, cancellationToken); var continuation = this.PackState(stateId, tokenPair.Client); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(continuation)))); } var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
public async Task <ActionResult <ApiResult <SessionPreview> > > RemovePassword([FromBody] UserPasswordRemoveModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; if (!user.ConnectedAccounts.Any()) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.GenericError, "To disable a password, at least one external account must be connected to this account.")))); } var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd == null || !await this.Password.ValidatePasswordHashAsync(data.Password, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } await this.UserRepository.UpdateUserPasswordAsync(user.Id, null, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
public async Task <ActionResult <ApiResult <bool> > > SubmitFlag([FromRoute] string id, [FromBody] ChallengeFlagModel challengeFlag, CancellationToken cancellationToken = default) { var challenge = await this.ChallengeRepository.GetChallengeAsync(id, cancellationToken); var flag = challengeFlag.Flag; var valid = flag == challenge.Flag; int?score = null; if (valid && this.EventConfiguration.Scoring != CtfScoringMode.Static) { var scoreInfo = await this.ScoreCalculator.ComputeCurrentScoreAsync(challenge, cancellationToken); if (this.EventConfiguration.Scoring == CtfScoringMode.Freezer) { score = scoreInfo.Current; } } var solve = await this.ChallengeRepository.SubmitSolveAsync(flag, valid, challenge.Id, this.RosettaUser.Id, this.RosettaUser.Team.Id, score, cancellationToken); if (solve == null) { return(this.Conflict(ApiResult.FromError <bool>(new ApiError(ApiErrorCode.AlreadySolved, "Your team already solved this challenge.")))); } if (valid && challenge.BaseScore == 1) { await this.ChallengeCacheRepository.IncrementBaselineSolveCountAsync(cancellationToken); if (this.EventConfiguration.Scoring != CtfScoringMode.Static) { await this.ScoreCalculator.UpdateAllScoresAsync(this.EventConfiguration.Scoring == CtfScoringMode.Freezer, false, cancellationToken); } } return(this.Ok(ApiResult.FromResult(valid))); }
public async Task <ActionResult <ApiResult <SessionPreview> > > ChangePassword([FromBody] UserPasswordChangeModel data, CancellationToken cancellationToken = default) { var user = this.RosettaUser; var pwd = await this.UserRepository.GetUserPasswordAsync(user.Id, cancellationToken); if (pwd != null && data.OldPassword == null) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } if (pwd != null && !await this.Password.ValidatePasswordHashAsync(data.OldPassword, pwd)) { return(this.StatusCode(401, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidCredentials, "Specified credentials were invalid.")))); } var npwd = await this.Password.CreatePasswordHashAsync(data.NewPassword); await this.UserRepository.UpdateUserPasswordAsync(user.Id, npwd, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }
public void FromError_ThrowsException_WhenArgumentsInvalid() { Assert.Throws <ArgumentNullException>(() => ApiResult.FromError(null, null)); Assert.Throws <ArgumentNullException>(() => ApiResult.FromError(null, new Exception())); Assert.Throws <ArgumentNullException>(() => ApiResult.FromError(ApiRequest.To(string.Empty), null)); }
public async Task <ActionResult <ApiResult <SessionPreview> > > Login([FromBody] OAuthAuthenticationModel data, CancellationToken cancellationToken = default) { if (data.State == null) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "OAuth state validation failed.")))); } var(stateId, clientTk) = this.UnpackState(data.State); var serverTk = await this.OAuthStateRepository.ValidateStateAsync(this.HttpContext.Connection.RemoteIpAddress.ToString(), stateId, cancellationToken); var tokenPair = new ActionTokenPair(clientTk, serverTk); if (!this.ActionTokenPairHandler.ValidateTokenPair(tokenPair, TokenActionOAuth)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "OAuth state validation failed.")))); } var provider = this.OAuthSelector.IdFromReferrer(new Uri(data.Referrer)); var oauth = this.OAuthSelector.GetById(provider); if (oauth == null) { return(this.NotFound(ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidProvider, "Specified provider does not exist.")))); } var ctx = this.CreateContext(provider, data.State); var tokens = await oauth.CompleteLoginAsync(ctx, data.Code, cancellationToken); if (tokens == null) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.ExternalAuthenticationError, "Failed to authenticate with the OAuth provider.")))); } var expires = DateTimeOffset.UtcNow.AddSeconds(tokens.ExpiresIn - 20); var ouser = await oauth.GetUserAsync(ctx, tokens.AccessToken, cancellationToken); if (ouser == null || !ouser.IsAuthorized) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.Unauthorized, "You are not authorized to participate.")))); } var oid = ouser.Id; var euser = await this.UserRepository.GetExternalAccountAsync(oid, provider, cancellationToken); var user = euser?.User; if (euser == null) { if (!AbstractionUtilities.NameRegex.IsMatch(ouser.Username)) { return(this.StatusCode(403, ApiResult.FromError <SessionPreview>(new ApiError(ApiErrorCode.InvalidName, "Specified username contained invalid characters.")))); } var uid = this.GetUserId(); if (uid == null) { user = await this.UserRepository.CreateUserAsync(ouser.Username, ouser.IsAuthorized, cancellationToken); } else { user = await this.UserRepository.GetUserAsync(uid.Value, cancellationToken); } euser = await this.UserRepository.ConnectExternalAccountAsync(user.Id, ouser.Id, ouser.Username, provider, cancellationToken); } await this.UserRepository.UpdateTokensAsync(user.Id, euser.ProviderId, tokens.AccessToken, tokens.RefreshToken, expires, cancellationToken); var ruser = this.UserPreviewRepository.GetUser(user); var token = this.Jwt.IssueToken(ruser); return(this.Ok(ApiResult.FromResult(this.UserPreviewRepository.GetSession(ruser, token.Token, token.ExpiresAt, user.RequiresMfa)))); }