Ejemplo n.º 1
0
        private async Task <IActionResult> AuthoriseUser(string authToken, AuthType authType, string firstName, string lastName)
        {
            if (authType == AuthType.Unknown)
            {
                return(BadRequest());
            }

            var metadata = await tokenUtil.GetMetadataForToken(authToken, authType).ConfigureAwait(false);

            if (metadata == null || string.IsNullOrWhiteSpace(metadata.AuthIdentifier))
            {
                return(BadRequest());
            }

            var user = await users.FetchUserForAuthIdentifier(metadata.AuthIdentifier, authType).ConfigureAwait(false);

            if (user.IsFailure)
            {
                return(StatusCode(500));
            }

            if (user.Value.HasValue)
            {
                var userId = user.Value.Value.UserId;

                if (string.IsNullOrWhiteSpace(user.Value.Value.ExternalPaymentProcessorId))
                {
                    try
                    {
                        var billingId = await billingManager.CreateCustomer(user.Value.Value).ConfigureAwait(false);

                        await users.UpdateUser(new UserPatch
                        {
                            ResourceId = userId,
                            ExternalPaymentProcessorId = new PatchOperation <string> {
                                Operation = OperationKind.Update, Value = billingId
                            }
                        }).ConfigureAwait(false);
                    }
                    catch (Exception)
                    {
                        return(StatusCode(500));
                    }
                }

                if (!string.IsNullOrWhiteSpace(firstName) || !string.IsNullOrWhiteSpace(lastName))
                {
                    await users.UpdateUser(new UserPatch
                    {
                        ResourceId = userId,
                        FirstName  = new PatchOperation <string> {
                            Operation = OperationKind.Update, Value = firstName ?? "Anonymous"
                        },
                        LastName = new PatchOperation <string> {
                            Operation = OperationKind.Update, Value = lastName
                        },
                    }).ConfigureAwait(false);
                }

                var existingSession = await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authType)
                                      .Ensure(s => s.HasValue, "Data found")
                                      .OnSuccess(s => s.Value)
                                      .ConfigureAwait(false);

                if (existingSession.IsFailure)
                {
                    var session = new UserSession
                    {
                        AuthToken       = authToken,
                        UserId          = userId,
                        TokenType       = (int)authType,
                        AuthTokenExpiry = metadata.Expiry
                    };

                    var sessionId = await userSessions.CreateUserSession(session).ConfigureAwait(false);

                    if (sessionId.IsFailure)
                    {
                        return(StatusCode(500));
                    }
                }
            }
            else
            {
                var newUser = new User {
                    IsVerified = true, WantAdvertising = false, RegistrationId = tokenUtil.GenerateToken(), FirstName = firstName ?? "Anonymous", LastName = lastName
                };
                switch (authType)
                {
                case AuthType.Apple:
                    newUser.AppleUserIdentifier = metadata.AuthIdentifier;
                    break;

                case AuthType.Google:
                    newUser.GoogleUserIdentifier = metadata.AuthIdentifier;
                    break;

                case AuthType.Facebook:
                    newUser.FacebookUserIdentifier = metadata.AuthIdentifier;
                    break;

                case AuthType.Unknown:
                    break;
                }
                var result = await users.CreateUser(newUser).ConfigureAwait(false);

                if (result.IsFailure)
                {
                    return(StatusCode(500));
                }

                var userId = result.Value.Value;

                try
                {
                    var billingId = await billingManager.CreateCustomer(newUser).ConfigureAwait(false);

                    await users.UpdateUser(new UserPatch
                    {
                        ResourceId = userId,
                        ExternalPaymentProcessorId = new PatchOperation <string> {
                            Operation = OperationKind.Update, Value = billingId
                        }
                    }).ConfigureAwait(false);
                }
                catch (Exception)
                {
                    return(StatusCode(500));
                }

                var existingSession = await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authType)
                                      .Ensure(s => s.HasValue, "Data found")
                                      .OnSuccess(s => s.Value)
                                      .ConfigureAwait(false);

                if (existingSession.IsFailure)
                {
                    var session = new UserSession
                    {
                        AuthToken       = authToken,
                        UserId          = userId,
                        TokenType       = (int)authType,
                        AuthTokenExpiry = metadata.Expiry
                    };

                    var sessionId = await userSessions.CreateUserSession(session).ConfigureAwait(false);

                    if (sessionId.IsFailure)
                    {
                        return(StatusCode(500));
                    }
                }
            }

            return(Ok());
        }
Ejemplo n.º 2
0
        private async Task<AuthorisationResult> EnforceRBACRequirements(AuthContext authContext, Microsoft.AspNetCore.Routing.RouteData routeData)
        {
            var userType = authContext.UserType;

            // Grab the route name via the [ActionName(...)] annotation on a controller method.
            // If you don't annotate your methods, or have not configured this route as authenticated, we won't apply any auth restrictions.
            var routeName = (string)routeData.Values["action"];

            if (routeName == null || !settings.Meta.AuthRequirements.ContainsKey(routeName))
            {
                return AuthorisationResult.InjectAndContinue;
            }

            var requirements = settings.Meta.AuthRequirements[routeName];

            Maybe<Employee> employee = null;
            Maybe<EmployeeRole> employeeRole = null;
            Maybe<User> user = null;

            if (userType != settings.Meta.AuthRequirements[routeName].UserType && UserType.Any != settings.Meta.AuthRequirements[routeName].UserType)
            {
                return AuthorisationResult.AbortUnauthorised;
            }

            if (authContext.AuthToken.HasNoValue)
            {
                return AuthorisationResult.AbortUnauthorised;
            }

            var authToken = authContext.AuthToken.Value;

            // Depending on the session type, attempt to fetch the equivalent model (User or Employee).
            if (userType == UserType.Employee)
            {
                employee = (await employeeSessions.FetchEmployeeSessionAndEmployeeFromToken(authToken).ConfigureAwait(false))
                  .OnBoth(x => x.IsSuccess
                    ? x.Value
                    : Maybe<Employee>.None
                  );

                if (employee.HasNoValue)
                {
                    return AuthorisationResult.AbortUnauthorised;
                }

                // For employees, their permissions are scoped to an employee role. First we fetch the role.
                employeeRole = (await employeeRoles.FetchEmployeeRole(employee.Value.RoleId).ConfigureAwait(false))
                  .OnBoth(x => x.IsSuccess
                    ? x.Value
                    : Maybe<EmployeeRole>.None
                  );

                // If the employee role wasn't found but the route didn't require any permissions, we let them through.
                if (employeeRole.HasNoValue && RouteRequiresAtLeastOnePermission(requirements))
                {
                    return AuthorisationResult.AbortUnauthorised;
                }

                // Verify each of the role permissions in turn, if one is missing and the route requires it, deny access.
                if (!RoleHasCorrectPermissions(employeeRole.Value, requirements))
                {
                    return AuthorisationResult.AbortUnauthorised;
                }
            }
            else if (userType == UserType.User)
            {
                user = (await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authContext.AuthType).ConfigureAwait(false))
                  .OnBoth(x => x.IsSuccess
                    ? x.Value
                    : Maybe<User>.None
                  );

                if (user.HasNoValue)
                {
                    return AuthorisationResult.AbortUnauthorised;
                }
            }

            // After verifying the user's permissions, update the context with relevant user data and continue.
            authContext.Employee = employee;
            authContext.EmployeeRole = employeeRole;
            authContext.User = user;

            return AuthorisationResult.Continue;
        }