Я совершенно новичок в Swift и Vapor;
Я пытаюсь разработать промежуточное ПО для авторизации, которое вызывается из моей UserModel (объект Fluent Model) и имеет требуемый уровень доступа (int) и Путь (строка) и
- Гарантирует, что пользователь аутентифицирован,
- Проверяет, соответствует ли экземпляр UserModel.Accesslevel => Пропущенному уровню необходимого доступа и, если нет, перенаправляет пользователь к «Пути».
Я пытался пару дней и всегда приближался, но так и не понял, что мне нужно.
У меня есть следующее (пожалуйста извините за плохо названные объекты):
import Vapor
public protocol Authorizable: Authenticatable {
associatedtype ProfileAccess: UserAuthorizable
}
/// status cached using `UserAuthorizable'
public protocol UserAuthorizable: Authorizable {
/// Session identifier type.
associatedtype AccessLevel: LosslessStringConvertible
/// Identifier identifier.
var accessLevel: AccessLevel { get }
}
extension Authorizable {
/// Basic middleware to redirect unauthenticated requests to the supplied path
///
/// - parameters:
/// - path: The path to redirect to if the request is not authenticated
public static func authorizeMiddleware(levelrequired: Int, path: String) -> Middleware {
return AuthorizeUserMiddleware<Self>(Self.self, levelrequired: levelrequired, path: path)
}
}
// Helper for creating authorization middleware.
///
//private final class AuthRedirectMiddleware<A>: Middleware
//where A: Authenticatable
final class AuthorizeUserMiddleware<A>: Middleware where A: Authorizable {
let levelrequired: Int
let path: String
let authLevel : Int
init(_ authorizableType: A.Type = A.self, levelrequired: Int, path: String) {
self.levelrequired = levelrequired
self.path = path
}
/// See Middleware.respond
public func respond(to req: Request, chainingTo next: Responder) -> EventLoopFuture<Response> {
if req.auth.has(A.self) {
print("--------")
print(path)
print(levelrequired)
**// print(A.ProfileAccess.AccessLevel) <- list line fails because the A.ProfileAccess.AccessLevel is a type not value**
print("--------")
}
return next.respond(to: req)
}
}
Я добавил следующее в свою пользовательскую модель
extension UserModel: Authorizable
{
typealias ProfileAccess = UserModel
}
extension UserModel: UserAuthorizable {
typealias AccessLevel = Int
var accessLevel: AccessLevel { self.userprofile! }
}
И Route как таковой
// setup the authentication process
let session = app.routes.grouped([
UserModelSessionAuthenticator(),
UserModelCredentialsAuthenticator(),
UserModel.authorizeMiddleware(levelrequired: 255, path: "/login"), // this will redirect the user when unauthenticted
UserModel.authRedirectMiddleware(path: "/login"), // this will redirect the user when unauthenticted
])
Путь и требуемый уровень правильно переданы, но я не могу получить экземпляр AccessLevel от текущего пользователя. (Я уверен, что у меня есть шляпа C ++, и из того, что я могу «догадаться», UserModel на самом деле не является заполненным экземпляром пользователя, хотя аутентификация уже завершена)
Я попытался слиться процесс 'SessionAuthenticator', использующий связанный тип для передачи информации об учетной записи.
Другой моей мыслью было проверить, аутентифицирован ли пользователь, и если да, то я могу с уверенностью предположить, что Session Cook ie содержит мой идентификатор пользователя и поэтому я мог бы вытащить пользователя из БД (снова) и проверить уровень доступа пользователей оттуда.
Я мог бы уйти отсюда, через пару дней я не знаю, какой способ лучше подход, любое руководство будет очень признательно.
Ура