예제 #1
0
        public async Task <IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return(Page());
            }

            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                return(NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."));
            }

            var thisPuzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(_context, User, _userManager);

            // enforce access rights, do not let these change!
            Input.ID             = thisPuzzleUser.ID;
            Input.IsGlobalAdmin  = thisPuzzleUser.IsGlobalAdmin;
            Input.IdentityUserId = thisPuzzleUser.IdentityUserId;

            _context.Entry(thisPuzzleUser).State = EntityState.Detached;
            _context.Attach(Input).State         = EntityState.Modified;

            await _context.SaveChangesAsync(true);

            await _signInManager.RefreshSignInAsync(user);

            StatusMessage = "Your profile has been updated";
            return(RedirectToPage());
        }
        public async Task <IActionResult> OnGetAddAdminAsync(int userId)
        {
            // Check that the user isn't already an admin
            if (await(from admin in _context.EventAdmins
                      where admin.Admin.ID == userId &&
                      admin.Event == Event
                      select admin).AnyAsync())
            {
                return(NotFound("User is already an admin in this event."));
            }

            EventAdmins Admin = new EventAdmins();

            PuzzleUser user = await _context.PuzzleUsers.FirstOrDefaultAsync(m => m.ID == userId);

            if (user == null)
            {
                return(NotFound("Could not find user with ID '" + userId + "'. Check to make sure the user hasn't been removed."));
            }
            Admin.Admin = user;

            Admin.Event = Event;

            _context.EventAdmins.Add(Admin);
            await _context.SaveChangesAsync();

            return(RedirectToPage("/Events/Players"));
        }
예제 #3
0
        public async Task <IActionResult> OnGetAddAuthorAsync(int userId)
        {
            // Check that the user isn't already an author
            if (await(from author in _context.EventAuthors
                      where author.Author.ID == userId &&
                      author.Event == Event
                      select author).AnyAsync())
            {
                return(NotFound("User is already an author in this event."));
            }

            EventAuthors Author = new EventAuthors();

            PuzzleUser user = await _context.PuzzleUsers.FirstOrDefaultAsync(m => m.ID == userId);

            if (user == null)
            {
                return(NotFound("Could not find user with ID '" + userId + "'. Check to make sure the user hasn't been removed."));
            }
            Author.Author = user;

            Author.Event = Event;

            _context.EventAuthors.Add(Author);
            user.MayBeAdminOrAuthor = true;

            await _context.SaveChangesAsync();

            return(RedirectToPage("/Events/Players"));
        }
        public async Task <IActionResult> Index(string eventId, int puzzleId)
        {
            Event currentEvent = await EventHelper.GetEventFromEventId(context, eventId);

            PuzzleUser user = await PuzzleUser.GetPuzzleUserForCurrentUser(context, User, userManager);

            Team team = await UserEventHelper.GetTeamForPlayer(context, currentEvent, user);

            Puzzle thisPuzzle = await context.Puzzles.FirstOrDefaultAsync(m => m.ID == puzzleId);

            // Find the material file with the latest-alphabetically ShortName that contains the substring "customPage".
            var materialFile = await(from f in context.ContentFiles
                                     where f.Puzzle == thisPuzzle && f.FileType == ContentFileType.PuzzleMaterial && f.ShortName.Contains("customPage")
                                     orderby f.ShortName descending
                                     select f).FirstOrDefaultAsync();

            if (materialFile == null)
            {
                return(Content("ERROR:  There's no custom page uploaded for this puzzle"));
            }

            var materialUrl = materialFile.Url;

            // Download that material file.
            string fileContents;

            using (var wc = new System.Net.WebClient())
            {
                fileContents = await wc.DownloadStringTaskAsync(materialUrl);
            }

            // Return the file contents to the user.
            return(Content(fileContents, "text/html"));
        }
        public async Task IsPuzzleAuthorCheck(AuthorizationHandlerContext authContext, IAuthorizationRequirement requirement)
        {
            EventRole role = GetEventRoleFromRoute();

            if (role != EventRole.author)
            {
                return;
            }

            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Puzzle puzzle = await GetPuzzleFromRoute();

            Event thisEvent = await GetEventFromRoute();

            if (thisEvent != null && await UserEventHelper.IsAuthorOfPuzzle(dbContext, puzzle, puzzleUser))
            {
                authContext.Succeed(requirement);
            }

            if (puzzle != null)
            {
                dbContext.Entry(puzzle).State = EntityState.Detached;
            }
        }
예제 #6
0
        public async Task <IActionResult> OnPostAsync(string returnUrl = null)
        {
            if (string.IsNullOrEmpty(PuzzleUser.Email))
            {
                ModelState.AddModelError("PuzzleUser.Email", "An email is required.");
            }
            else if (!MailHelper.IsValidEmail(PuzzleUser.Email))
            {
                ModelState.AddModelError("PuzzleUser.Email", "This email address is not valid.");
            }

            if (!ModelState.IsValid)
            {
                return(Page());
            }

            var thisPuzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(_context, User, _userManager);

            if (thisPuzzleUser != null)
            {
                _context.Entry(thisPuzzleUser).State = EntityState.Detached;
            }

            _context.Attach(PuzzleUser).State = EntityState.Modified;

            await _context.SaveChangesAsync();

            return(Redirect(returnUrl));
        }
예제 #7
0
        public async Task <IActionResult> Post(string eventId, int puzzleId, List <int> query_puzzle_ids, int?min_solve_count, string annotations,
                                               string last_sync_time)
        {
            // Find what team this user is on, relative to the event.

            Event currentEvent = await EventHelper.GetEventFromEventId(context, eventId);

            if (currentEvent == null)
            {
                return(Unauthorized());
            }
            PuzzleUser user = await PuzzleUser.GetPuzzleUserForCurrentUser(context, User, userManager);

            if (user == null)
            {
                return(Unauthorized());
            }
            Team team = await UserEventHelper.GetTeamForPlayer(context, currentEvent, user);

            if (team == null)
            {
                return(Unauthorized());
            }

            var helper   = new SyncHelper(context);
            var response = await helper.GetSyncResponse(currentEvent.ID, team.ID, puzzleId, query_puzzle_ids, min_solve_count,
                                                        annotations, last_sync_time, false);

            return(Json(response));
        }
        public async Task IsPlayerOnTeamCheck(AuthorizationHandlerContext authContext, IAuthorizationRequirement requirement)
        {
            EventRole role = GetEventRoleFromRoute();

            if (role != EventRole.play)
            {
                return;
            }

            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Team team = await GetTeamFromRoute();

            Event thisEvent = await GetEventFromRoute();

            if (thisEvent != null)
            {
                Team userTeam = await UserEventHelper.GetTeamForPlayer(dbContext, thisEvent, puzzleUser);

                if (userTeam != null && userTeam.ID == team.ID)
                {
                    authContext.Succeed(requirement);
                }
            }
        }
        /// <summary>
        /// Runs before page actions
        /// </summary>
        public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
        {
            LoggedInUser = await PuzzleUser.GetPuzzleUserForCurrentUser(_context, User, userManager);

            // Required to have the rest of page execution occur
            await next.Invoke();
        }
예제 #10
0
        public async Task <IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return(Page());
            }

            _context.Events.Add(Event);

            var loggedInUser = await PuzzleUser.GetPuzzleUserForCurrentUser(_context, User, _userManager);

            if (loggedInUser != null)
            {
                _context.EventAdmins.Add(new EventAdmins()
                {
                    Event = Event, Admin = loggedInUser
                });
                _context.EventAuthors.Add(new EventAuthors()
                {
                    Event = Event, Author = loggedInUser
                });
            }

            await _context.SaveChangesAsync();

            return(RedirectToPage("./Index"));
        }
        /// <summary>
        /// Set the solve state of some puzzle state records. In the course of setting the state, instantiate any state records that are missing on the server.
        /// </summary>
        /// <param name="context">The puzzle DB context</param>
        /// <param name="eventObj">The event we are querying from</param>
        /// <param name="puzzle">
        ///     The puzzle; if null, get all puzzles in the event.
        /// </param>
        /// <param name="team">
        ///     The team; if null, get all the teams in the event.
        /// </param>
        /// <param name="value">The solve time (null if unsolving)</param>
        /// <param name="author"></param>
        /// <returns>
        ///     A task that can be awaited for the solve/unsolve operation
        /// </returns>
        public static async Task SetSolveStateAsync(
            PuzzleServerContext context,
            Event eventObj,
            Puzzle puzzle,
            Team team,
            DateTime?value,
            PuzzleUser author = null)
        {
            IQueryable <PuzzleStatePerTeam> statesQ = PuzzleStateHelper
                                                      .GetFullReadWriteQuery(context, eventObj, puzzle, team, author);

            List <PuzzleStatePerTeam> states = await statesQ.ToListAsync();

            for (int i = 0; i < states.Count; i++)
            {
                // Only allow solved time to be modified if it is being marked as unsolved (set to null) or if it is being solved for the first time
                if (value == null || states[i].SolvedTime == null)
                {
                    // Unlock puzzles when solving them
                    if (value != null && states[i].UnlockedTime == null)
                    {
                        states[i].UnlockedTime = value;
                    }

                    states[i].SolvedTime = value;
                }
            }

            // Award hint coins
            if (value != null && puzzle != null && puzzle.HintCoinsForSolve != 0)
            {
                if (team != null)
                {
                    team.HintCoinCount += puzzle.HintCoinsForSolve;
                }
                else
                {
                    var allTeams = from Team curTeam in context.Teams
                                   where curTeam.Event == eventObj
                                   select curTeam;
                    foreach (Team curTeam in allTeams)
                    {
                        curTeam.HintCoinCount += puzzle.HintCoinsForSolve;
                    }
                }
            }

            await context.SaveChangesAsync();

            // if this puzzle got solved, look for others to unlock
            if (puzzle != null && value != null)
            {
                await UnlockAnyPuzzlesThatThisSolveUnlockedAsync(context,
                                                                 eventObj,
                                                                 puzzle,
                                                                 team,
                                                                 value.Value);
            }
        }
        public async Task <SubmissionResponse> PostSubmitAnswerAsync([FromBody] AnswerSubmission submission, [FromRoute] string eventId, [FromRoute] int puzzleId)
        {
            Event currentEvent = await EventHelper.GetEventFromEventId(context, eventId);

            PuzzleUser user = await PuzzleUser.GetPuzzleUserForCurrentUser(context, User, userManager);

            return(await SubmissionEvaluator.EvaluateSubmission(context, user, currentEvent, puzzleId, submission.SubmissionText, submission.AllowFreeformSharing));
        }
예제 #13
0
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authContext,
                                                             IsGlobalAdminRequirement requirement)
        {
            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            if (puzzleUser.IsGlobalAdmin)
            {
                authContext.Succeed(requirement);
            }
        }
예제 #14
0
        /// <summary>
        /// Adds a user to a team after performing a number of checks to make sure that the change is valid
        /// </summary>
        /// <param name="context">The context to update</param>
        /// <param name="Event">The event that the team is for</param>
        /// <param name="EventRole">The event role of the user that is making this change</param>
        /// <param name="teamId">The id of the team the player should be added to</param>
        /// <param name="userId">The user that should be added to the team</param>
        /// <returns>
        /// A tuple where the first element is a boolean that indicates whether the player was successfully
        /// added to the team and the second element is a message to display that explains the error in the
        /// case where the user was not successfully added to the team
        /// </returns>
        public static async Task <Tuple <bool, string> > AddMemberAsync(PuzzleServerContext context, Event Event, EventRole EventRole, int teamId, int userId)
        {
            Team team = await context.Teams.FirstOrDefaultAsync(m => m.ID == teamId);

            if (team == null)
            {
                return(new Tuple <bool, string>(false, $"Could not find team with ID '{teamId}'. Check to make sure the team hasn't been removed."));
            }

            var currentTeamMembers = await context.TeamMembers.Where(members => members.Team.ID == team.ID).ToListAsync();

            if (currentTeamMembers.Count >= Event.MaxTeamSize && EventRole != EventRole.admin)
            {
                return(new Tuple <bool, string>(false, $"The team '{team.Name}' is full."));
            }

            PuzzleUser user = await context.PuzzleUsers.FirstOrDefaultAsync(m => m.ID == userId);

            if (user == null)
            {
                return(new Tuple <bool, string>(false, $"Could not find user with ID '{userId}'. Check to make sure the user hasn't been removed."));
            }

            if (user.EmployeeAlias == null && currentTeamMembers.Where((m) => m.Member.EmployeeAlias == null).Count() >= Event.MaxExternalsPerTeam)
            {
                return(new Tuple <bool, string>(false, $"The team '{team.Name}' is already at its maximum count of non-employee players, and '{user.Email}' has no registered alias."));
            }

            if (await(from teamMember in context.TeamMembers
                      where teamMember.Member == user &&
                      teamMember.Team.Event == Event
                      select teamMember).AnyAsync())
            {
                return(new Tuple <bool, string>(false, $"'{user.Email}' is already on a team in this event."));
            }

            TeamMembers Member = new TeamMembers();

            Member.Team   = team;
            Member.Member = user;

            // Remove any applications the user might have started for this event
            var allApplications = from app in context.TeamApplications
                                  where app.Player == user &&
                                  app.Team.Event == Event
                                  select app;

            context.TeamApplications.RemoveRange(allApplications);

            context.TeamMembers.Add(Member);
            await context.SaveChangesAsync();

            return(new Tuple <bool, string>(true, ""));
        }
예제 #15
0
        public static async Task IsEventAdminCheck(AuthorizationHandlerContext authContext, PuzzleServerContext dbContext, UserManager <IdentityUser> userManager, IAuthorizationRequirement requirement)
        {
            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Event thisEvent = await AuthorizationHelper.GetEventFromContext(authContext);

            EventRole role = AuthorizationHelper.GetEventRoleFromContext(authContext);

            if (thisEvent != null && role == EventRole.admin && await puzzleUser.IsAdminForEvent(dbContext, thisEvent))
            {
                authContext.Succeed(requirement);
            }
        }
예제 #16
0
        public async Task <IActionResult> OnGetAsync(string eventId, int puzzleId)
        {
            Event currentEvent = await EventHelper.GetEventFromEventId(_context, eventId);

            if (currentEvent == null)
            {
                return(Unauthorized());
            }
            EventId = currentEvent.ID;

            PuzzleUser user = LoggedInUser;

            if (user == null)
            {
                return(Unauthorized());
            }

            Team team = await UserEventHelper.GetTeamForPlayer(_context, currentEvent, user);

            if (team == null)
            {
                return(Unauthorized());
            }

            Puzzle kitchenSyncPuzzle = await _context.Puzzles.FirstOrDefaultAsync(m => m.Name == "Kitchen Sync" && m.Event.ID == EventId);

            KitchenSyncId = kitchenSyncPuzzle.ID;
            Puzzle heatSyncPuzzle = await _context.Puzzles.FirstOrDefaultAsync(m => m.Name == "Heat Sync" && m.Event.ID == EventId);

            HeatSyncId = heatSyncPuzzle.ID;
            Puzzle lipSyncPuzzle = await _context.Puzzles.FirstOrDefaultAsync(m => m.Name == "Lip Sync" && m.Event.ID == EventId);

            LipSyncId = lipSyncPuzzle.ID;
            Puzzle syncTestMetapuzzle = await _context.Puzzles.FirstOrDefaultAsync(m => m.Name == "Sync Test" && m.Event.ID == EventId);

            MetapuzzleId = syncTestMetapuzzle.ID;

            var        helper           = new SyncHelper(_context);
            List <int> query_puzzle_ids = new List <int> {
                KitchenSyncId, HeatSyncId, LipSyncId
            };
            var response = await helper.GetSyncResponse(currentEvent.ID, team.ID, puzzleId, query_puzzle_ids, 0, null, null);

            var responseSerialized = JsonConvert.SerializeObject(response);

            InitialSyncString = HttpUtility.JavaScriptStringEncode(responseSerialized);

            return(Page());
        }
예제 #17
0
        /// <summary>
        /// Set the solve state of some puzzle state records. In the course of setting the state, instantiate any state records that are missing on the server.
        /// </summary>
        /// <param name="context">The puzzle DB context</param>
        /// <param name="eventObj">The event we are querying from</param>
        /// <param name="puzzle">
        ///     The puzzle; if null, get all puzzles in the event.
        /// </param>
        /// <param name="team">
        ///     The team; if null, get all the teams in the event.
        /// </param>
        /// <param name="value">The solve time (null if unsolving)</param>
        /// <param name="author"></param>
        /// <returns>
        ///     A task that can be awaited for the solve/unsolve operation
        /// </returns>
        public static async Task SetSolveStateAsync(
            PuzzleServerContext context,
            Event eventObj,
            Puzzle puzzle,
            Team team,
            DateTime?value,
            PuzzleUser author = null)
        {
            IQueryable <PuzzleStatePerTeam> statesQ = await PuzzleStateHelper
                                                      .GetFullReadWriteQueryAsync(context, eventObj, puzzle, team, author);

            List <PuzzleStatePerTeam> states = await statesQ.ToListAsync();

            for (int i = 0; i < states.Count; i++)
            {
                states[i].SolvedTime = value;
            }

            // Award hint coins
            if (value != null && puzzle != null && puzzle.HintCoinsForSolve != 0)
            {
                if (team != null)
                {
                    team.HintCoinCount += puzzle.HintCoinsForSolve;
                }
                else
                {
                    var allTeams = from Team curTeam in context.Teams
                                   where curTeam.Event == eventObj
                                   select curTeam;
                    foreach (Team curTeam in allTeams)
                    {
                        curTeam.HintCoinCount += puzzle.HintCoinsForSolve;
                    }
                }
            }

            await context.SaveChangesAsync();

            // if this puzzle got solved, look for others to unlock
            if (value != null)
            {
                await UnlockAnyPuzzlesThatThisSolveUnlockedAsync(context,
                                                                 eventObj,
                                                                 puzzle,
                                                                 team,
                                                                 value.Value);
            }
        }
        public async Task IsEventAdminCheck(AuthorizationHandlerContext authContext, IAuthorizationRequirement requirement)
        {
            EventRole role = GetEventRoleFromRoute();

            if (role != EventRole.admin)
            {
                return;
            }

            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Event thisEvent = await GetEventFromRoute();

            if (thisEvent != null && puzzleUser != null && await puzzleUser.IsAdminForEvent(dbContext, thisEvent))
            {
                authContext.Succeed(requirement);
            }
        }
        public async Task <IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }
            var info = await _signInManager.GetExternalLoginInfoAsync();

            if (info == null)
            {
                ErrorMessage = "Error loading external login information.";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent : false, bypassTwoFactor : true);

            if (result.Succeeded)
            {
                _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
                return(LocalRedirect(returnUrl));
            }
            if (result.IsLockedOut)
            {
                return(RedirectToPage("./Lockout"));
            }
            else
            {
                // If the user does not have an account, then ask the user to create an account.
                ReturnUrl     = returnUrl;
                LoginProvider = info.LoginProvider;
                if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
                {
                    Input = new PuzzleUser
                    {
                        Email          = info.Principal.FindFirstValue(ClaimTypes.Email),
                        IdentityUserId = "fake"
                    };
                }
                return(Page());
            }
        }
예제 #20
0
        public async Task <IActionResult> OnGetAsync(string eventId, int puzzleId)
        {
            Event currentEvent = await EventHelper.GetEventFromEventId(_context, eventId);

            if (currentEvent == null)
            {
                return(Unauthorized());
            }
            EventId = currentEvent.ID;

            PuzzleUser user = LoggedInUser;

            if (user == null)
            {
                return(Unauthorized());
            }

            Team team = await UserEventHelper.GetTeamForPlayer(_context, currentEvent, user);

            if (team == null)
            {
                return(Unauthorized());
            }

            Puzzle thisPuzzle = await _context.Puzzles.FirstOrDefaultAsync(m => m.ID == puzzleId && m.Event.ID == EventId);

            if (thisPuzzle == null || !thisPuzzle.Name.Equals("The Play That Goes Wrong"))
            {
                return(Unauthorized());
            }
            MetapuzzleId = puzzleId;

            var        helper           = new SyncHelper(_context);
            List <int> query_puzzle_ids = Enumerable.Range(MetapuzzleId - 10, 11).ToList();
            var        response         = await helper.GetSyncResponse(currentEvent.ID, team.ID, puzzleId, query_puzzle_ids, 0, null, null);

            var responseSerialized = JsonConvert.SerializeObject(response);

            InitialSyncString = HttpUtility.JavaScriptStringEncode(responseSerialized);

            return(Page());
        }
예제 #21
0
        public async Task <IActionResult> OnPostAsync(string returnUrl = null)
        {
            if (!ModelState.IsValid)
            {
                return(Page());
            }

            var thisPuzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(_context, User, _userManager);

            if (thisPuzzleUser != null)
            {
                _context.Entry(thisPuzzleUser).State = EntityState.Detached;
            }

            _context.Attach(PuzzleUser).State = EntityState.Modified;

            await _context.SaveChangesAsync();

            return(Redirect(returnUrl));
        }
예제 #22
0
        public static async Task IsPuzzleAuthorCheck(AuthorizationHandlerContext authContext, PuzzleServerContext dbContext, UserManager <IdentityUser> userManager, IAuthorizationRequirement requirement)
        {
            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Puzzle puzzle = await AuthorizationHelper.GetPuzzleFromContext(authContext);

            Event thisEvent = await AuthorizationHelper.GetEventFromContext(authContext);

            EventRole role = AuthorizationHelper.GetEventRoleFromContext(authContext);

            if (thisEvent != null && role == EventRole.author && await UserEventHelper.IsAuthorOfPuzzle(dbContext, puzzle, puzzleUser))
            {
                authContext.Succeed(requirement);
            }

            if (puzzle != null)
            {
                dbContext.Entry(puzzle).State = EntityState.Detached;
            }
        }
예제 #23
0
        public static async Task IsPlayerOnTeamCheck(AuthorizationHandlerContext authContext, PuzzleServerContext dbContext, UserManager <IdentityUser> userManager, IAuthorizationRequirement requirement)
        {
            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Team team = await AuthorizationHelper.GetTeamFromContext(authContext);

            Event thisEvent = await AuthorizationHelper.GetEventFromContext(authContext);

            EventRole role = AuthorizationHelper.GetEventRoleFromContext(authContext);

            if (thisEvent != null && role == EventRole.play)
            {
                Team userTeam = await UserEventHelper.GetTeamForPlayer(dbContext, thisEvent, puzzleUser);

                if (userTeam != null && userTeam.ID == team.ID)
                {
                    authContext.Succeed(requirement);
                }
            }
        }
예제 #24
0
        /// <summary>
        /// Set the lockout expiry time of some puzzle state records. In the
        /// course of setting the state, instantiate any state records that are
        /// missing on the server.
        /// </summary>
        /// <param name="context">The puzzle DB context</param>
        /// <param name="eventObj">The event we are querying from</param>
        /// <param name="puzzle">
        ///     The puzzle; if null, get all puzzles in the event.
        /// </param>
        /// <param name="team">
        ///     The team; if null, get all the teams in the event.
        /// </param>
        /// <param name="value">The Lockout expiry time<param>
        /// <param name="author"></param>
        /// <returns>
        ///     A task that can be awaited for the lockout operation
        /// </returns>
        public static async Task SetLockoutExpiryTimeAsync(
            PuzzleServerContext context,
            Event eventObj,
            Puzzle puzzle,
            Team team,
            DateTime?value,
            PuzzleUser author = null)
        {
            IQueryable <PuzzleStatePerTeam> statesQ = await PuzzleStateHelper
                                                      .GetFullReadWriteQueryAsync(context, eventObj, puzzle, team, author);

            List <PuzzleStatePerTeam> states = await statesQ.ToListAsync();

            for (int i = 0; i < states.Count; i++)
            {
                states[i].LockoutExpiryTime = value;
            }

            await context.SaveChangesAsync();
        }
        public static async Task IsEventAuthorCheck(AuthorizationHandlerContext authContext, PuzzleServerContext dbContext, UserManager <IdentityUser> userManager, IAuthorizationRequirement requirement)
        {
            EventRole role = AuthorizationHelper.GetEventRoleFromContext(authContext);

            if (role != EventRole.author)
            {
                return;
            }

            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            if (authContext.Resource is AuthorizationFilterContext filterContext)
            {
                Event thisEvent = await AuthorizationHelper.GetEventFromContext(authContext);

                if (thisEvent != null && await puzzleUser.IsAuthorForEvent(dbContext, thisEvent))
                {
                    authContext.Succeed(requirement);
                }
            }
        }
예제 #26
0
        public async Task <IActionResult> OnGetAsync()
        {
            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                return(NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."));
            }

            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUser(user.Id, _context);

            var userName = await _userManager.GetUserNameAsync(user);

            Username = userName;

            Input = puzzleUser;

            IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);

            return(Page());
        }
        public async Task PlayerCanSeePuzzleCheck(AuthorizationHandlerContext authContext, IAuthorizationRequirement requirement)
        {
            PuzzleUser puzzleUser = await PuzzleUser.GetPuzzleUserForCurrentUser(dbContext, authContext.User, userManager);

            Puzzle puzzle = await GetPuzzleFromRoute();

            Event thisEvent = await GetEventFromRoute();

            if (thisEvent != null && puzzle != null)
            {
                Team team = await UserEventHelper.GetTeamForPlayer(dbContext, thisEvent, puzzleUser);

                if (team != null)
                {
                    IQueryable <PuzzleStatePerTeam> statesQ = PuzzleStateHelper.GetFullReadOnlyQuery(dbContext, thisEvent, puzzle, team);

                    if (statesQ.FirstOrDefault().UnlockedTime != null || thisEvent.AreAnswersAvailableNow)
                    {
                        authContext.Succeed(requirement);
                    }
                }
            }
        }
예제 #28
0
        /// <summary>
        /// Set the email only mode of some puzzle state records. In the course
        /// of setting the state, instantiate any state records that are
        /// missing on the server.
        /// </summary>
        /// <param name="context">The puzzle DB context</param>
        /// <param name="eventObj">The event we are querying from</param>
        /// <param name="puzzle">
        ///     The puzzle; if null, get all puzzles in the event.
        /// </param>
        /// <param name="team">
        ///     The team; if null, get all the teams in the event.
        /// </param>
        /// <param name="value">The new email only state for the puzzle</param>
        /// <param name="author"></param>
        /// <returns>
        ///     A task that can be awaited for the lockout operation
        /// </returns>
        public static async Task SetEmailOnlyModeAsync(
            PuzzleServerContext context,
            Event eventObj,
            Puzzle puzzle,
            Team team,
            bool value,
            PuzzleUser author = null)
        {
            IQueryable <PuzzleStatePerTeam> statesQ = await PuzzleStateHelper
                                                      .GetFullReadWriteQueryAsync(context, eventObj, puzzle, team, author);

            List <PuzzleStatePerTeam> states = await statesQ.ToListAsync();

            for (int i = 0; i < states.Count; i++)
            {
                states[i].IsEmailOnlyMode = value;
                if (value == true)
                {
                    states[i].WrongSubmissionCountBuffer += 50;
                }
            }

            await context.SaveChangesAsync();
        }
예제 #29
0
        public async Task <IActionResult> Index(string eventId, int puzzleId)
        {
            Event currentEvent = await EventHelper.GetEventFromEventId(context, eventId);

            if (currentEvent == null)
            {
                return(Content("ERROR:  That event doesn't exist"));
            }

            PuzzleUser user = await PuzzleUser.GetPuzzleUserForCurrentUser(context, User, userManager);

            if (user == null)
            {
                return(Content("ERROR:  You aren't logged in"));
            }

            Team team = await UserEventHelper.GetTeamForPlayer(context, currentEvent, user);

            if (team == null)
            {
                return(Content("ERROR:  You're not on a team"));
            }

            Puzzle thisPuzzle = await context.Puzzles.FirstOrDefaultAsync(m => m.ID == puzzleId);

            if (thisPuzzle == null)
            {
                return(Content("ERROR:  That's not a valid puzzle ID"));
            }

            if (!currentEvent.AreAnswersAvailableNow)
            {
                var puzzleState = await(from state in context.PuzzleStatePerTeam
                                        where state.Puzzle == thisPuzzle && state.Team == team
                                        select state).FirstOrDefaultAsync();
                if (puzzleState == null || puzzleState.UnlockedTime == null)
                {
                    return(Content("ERROR:  You haven't unlocked this puzzle yet"));
                }
            }

            // Find the material file with the latest-alphabetically ShortName that contains the substring "client".

            var materialFile = await(from f in context.ContentFiles
                                     where f.Puzzle == thisPuzzle && f.FileType == ContentFileType.PuzzleMaterial && f.ShortName.Contains("client")
                                     orderby f.ShortName descending
                                     select f).FirstOrDefaultAsync();

            if (materialFile == null)
            {
                return(Content("ERROR:  There's no sync client registered for this puzzle"));
            }

            var materialUrl = materialFile.Url;

            // Start doing a sync asynchronously while we download the file contents.

            var helper = new SyncHelper(context);
            Task <Dictionary <string, object> > responseTask = helper.GetSyncResponse(currentEvent.ID, team.ID, puzzleId, null, 0, null, null, true);

            // Download that material file.

            string fileContents;

            using (var wc = new System.Net.WebClient())
            {
                fileContents = await wc.DownloadStringTaskAsync(materialUrl);
            }

            // Wait for the asynchronous sync we started earlier to complete, then serialize
            // its results and use them to replace the substring "@SYNC" where it appears
            // in the downloaded file contents.

            Dictionary <string, object> response = await responseTask;
            var responseSerialized = JsonConvert.SerializeObject(response);
            var initialSyncString  = HttpUtility.JavaScriptStringEncode(responseSerialized);

            fileContents = fileContents.Replace("@SYNC", initialSyncString);

            // Return the file contents to the user.

            return(Content(fileContents, "text/html"));
        }
예제 #30
0
        /// <summary>
        /// Adds a user to a team after performing a number of checks to make sure that the change is valid
        /// </summary>
        /// <param name="context">The context to update</param>
        /// <param name="Event">The event that the team is for</param>
        /// <param name="EventRole">The event role of the user that is making this change</param>
        /// <param name="teamId">The id of the team the player should be added to</param>
        /// <param name="userId">The user that should be added to the team</param>
        /// <returns>
        /// A tuple where the first element is a boolean that indicates whether the player was successfully
        /// added to the team and the second element is a message to display that explains the error in the
        /// case where the user was not successfully added to the team
        /// </returns>
        public static async Task <Tuple <bool, string> > AddMemberAsync(PuzzleServerContext context, Event Event, EventRole EventRole, int teamId, int userId)
        {
            Team team = await context.Teams.FirstOrDefaultAsync(m => m.ID == teamId);

            if (team == null)
            {
                return(new Tuple <bool, string>(false, $"Could not find team with ID '{teamId}'. Check to make sure the team hasn't been removed."));
            }

            var currentTeamMembers = await context.TeamMembers.Where(members => members.Team.ID == team.ID).ToListAsync();

            if (currentTeamMembers.Count >= Event.MaxTeamSize && EventRole != EventRole.admin)
            {
                return(new Tuple <bool, string>(false, $"The team '{team.Name}' is full."));
            }

            PuzzleUser user = await context.PuzzleUsers.FirstOrDefaultAsync(m => m.ID == userId);

            if (user == null)
            {
                return(new Tuple <bool, string>(false, $"Could not find user with ID '{userId}'. Check to make sure the user hasn't been removed."));
            }

            if (user.EmployeeAlias == null && currentTeamMembers.Where((m) => m.Member.EmployeeAlias == null).Count() >= Event.MaxExternalsPerTeam)
            {
                return(new Tuple <bool, string>(false, $"The team '{team.Name}' is already at its maximum count of non-employee players, and '{user.Email}' has no registered alias."));
            }

            if (await(from teamMember in context.TeamMembers
                      where teamMember.Member == user &&
                      teamMember.Team.Event == Event
                      select teamMember).AnyAsync())
            {
                return(new Tuple <bool, string>(false, $"'{user.Email}' is already on a team in this event."));
            }

            TeamMembers Member = new TeamMembers();

            Member.Team   = team;
            Member.Member = user;

            // Remove any applications the user might have started for this event
            var allApplications = from app in context.TeamApplications
                                  where app.Player == user &&
                                  app.Team.Event == Event
                                  select app;

            context.TeamApplications.RemoveRange(allApplications);

            context.TeamMembers.Add(Member);
            await context.SaveChangesAsync();

            MailHelper.Singleton.SendPlaintextWithoutBcc(new string[] { team.PrimaryContactEmail, user.Email },
                                                         $"{Event.Name}: {user.Name} has now joined {team.Name}!",
                                                         $"Have a great time!");

            var teamCount = await context.TeamMembers.Where(members => members.Team.ID == team.ID).CountAsync();

            if (teamCount >= Event.MaxTeamSize)
            {
                var extraApplications = await(from app in context.TeamApplications
                                              where app.Team == team
                                              select app).ToListAsync();
                context.TeamApplications.RemoveRange(extraApplications);

                var extraApplicationMails = from app in extraApplications
                                            select app.Player.Email;

                MailHelper.Singleton.SendPlaintextBcc(extraApplicationMails.ToList(),
                                                      $"{Event.Name}: You can no longer join {team.Name} because it is now full",
                                                      $"Sorry! You can apply to another team if you wish.");
            }

            return(new Tuple <bool, string>(true, ""));
        }