Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit 9600af1

Browse files
Merge pull request #100 from nodes-vapor/feature/require-role-leaf-tag
Added requireRole leaf tag. Removed default .unknown role type
2 parents 54758cd + aa7f27d commit 9600af1

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

Sources/AdminPanel/Models/AdminPanelUser+AdminPanelUserType.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extension AdminPanelUser: AdminPanelUserType {
3535
public let name: String
3636
public let title: String?
3737
public let avatarUrl: String?
38-
public let role: AdminPanelUserRole
38+
public let role: AdminPanelUserRole?
3939
public let password: String
4040
public let passwordRepeat: String
4141
public let shouldResetPassword: Bool?
@@ -92,27 +92,23 @@ public enum AdminPanelUserRole: String {
9292
case superAdmin
9393
case admin
9494
case user
95-
case unknown
9695

97-
public var weight: Int {
96+
public var weight: UInt {
9897
switch self {
9998
case .superAdmin: return 3
10099
case .admin: return 2
101100
case .user: return 1
102-
case .unknown: return 0
103101
}
104102
}
105103

106104
public typealias RawValue = String
107105

108-
public init(rawValue: String?) {
109-
guard let rawValue = rawValue else { self = .unknown; return }
110-
106+
public init?(rawValue: String?) {
111107
switch rawValue {
112108
case AdminPanelUserRole.superAdmin.rawValue: self = .superAdmin
113109
case AdminPanelUserRole.admin.rawValue: self = .admin
114110
case AdminPanelUserRole.user.rawValue: self = .user
115-
default: self = .unknown
111+
default: return nil
116112
}
117113
}
118114
}
@@ -132,11 +128,17 @@ extension AdminPanelUserRole: AdminPanelUserRoleType {
132128
return "AdminPanel/Layout/Partials/Sidebars/admin"
133129
case .user:
134130
return "AdminPanel/Layout/Partials/Sidebars/user"
135-
case .unknown:
136-
return ""
137131
}
138132
}
139133

134+
public init?(_ description: String) {
135+
guard let role = AdminPanelUserRole.init(rawValue: description) else {
136+
return nil
137+
}
138+
139+
self = role
140+
}
141+
140142
public var description: String {
141143
return self.rawValue
142144
}

Sources/AdminPanel/Models/AdminPanelUser+Submittable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ extension AdminPanelUser: Submittable {
2020
email = user?.email
2121
name = user?.name
2222
title = user?.title
23-
role = user?.role.rawValue
23+
role = user?.role?.rawValue
2424
password = nil
2525
passwordAgain = nil
2626
shouldResetPassword = user?.shouldResetPassword
@@ -56,7 +56,7 @@ extension AdminPanelUser: Submittable {
5656
keyPath: \.role,
5757
label: "Role",
5858
validators: [.count(...191)],
59-
isRequired: false
59+
isRequired: true
6060
),
6161
makeFieldEntry(
6262
keyPath: \.password,
@@ -88,7 +88,7 @@ extension AdminPanelUser: Submittable {
8888
let email: String
8989
let name: String
9090
let title: String?
91-
let role: String
91+
let role: String?
9292
let password: String
9393
let shouldResetPassword: Bool?
9494
let shouldSpecifyPassword: Bool?

Sources/AdminPanel/Models/AdminPanelUser.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public final class AdminPanelUser: Codable {
88
public var name: String
99
public var title: String?
1010
public var avatarUrl: String?
11-
public var role: AdminPanelUserRole
11+
public var role: AdminPanelUserRole?
1212
public var password: String
1313
public var passwordChangeCount: Int
1414
public var shouldResetPassword: Bool
@@ -27,7 +27,7 @@ public final class AdminPanelUser: Codable {
2727
name: String,
2828
title: String? = nil,
2929
avatarUrl: String? = nil,
30-
role: AdminPanelUserRole,
30+
role: AdminPanelUserRole?,
3131
password: String,
3232
passwordChangeCount: Int = 0,
3333
shouldResetPassword: Bool = false
@@ -57,8 +57,7 @@ extension AdminPanelUser: Migration {
5757
type: .enum([
5858
AdminPanelUserRole.superAdmin.rawValue,
5959
AdminPanelUserRole.admin.rawValue,
60-
AdminPanelUserRole.user.rawValue,
61-
AdminPanelUserRole.unknown.rawValue
60+
AdminPanelUserRole.user.rawValue
6261
]))
6362
}
6463
}

Sources/AdminPanel/Models/AdminPanelUserType.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Reset
33
import Submissions
44
import Sugar
55

6-
public typealias SidebarMenuPathGenerator<U: AdminPanelUserRoleType> = ((U) -> String)
6+
public typealias SidebarMenuPathGenerator<U: AdminPanelUserRoleType> = ((U?) -> String)
77

88
public protocol AdminPanelUserType:
99
Parameter,
@@ -19,7 +19,7 @@ where
1919
associatedtype Role: AdminPanelUserRoleType
2020

2121
var shouldResetPassword: Bool { get }
22-
var role: Role { get }
22+
var role: Role? { get }
2323
func didCreate(with: Submission, on req: Request) throws -> Future<Void>
2424
}
2525

@@ -29,13 +29,17 @@ extension AdminPanelUserType {
2929
}
3030
}
3131

32-
public protocol AdminPanelUserRoleType: CustomStringConvertible, Comparable, Codable {
32+
public protocol AdminPanelUserRoleType: LosslessStringConvertible, Comparable, Codable {
3333
var menuPath: String { get }
3434
}
3535

3636
public extension AdminPanelUserType {
37-
public func requireRole(_ role: Self.Role) throws {
38-
guard self.role >= role else {
37+
public func requireRole(_ role: Self.Role?) throws {
38+
guard
39+
let myRole = self.role,
40+
let requiredRole = role,
41+
myRole >= requiredRole
42+
else {
3943
throw Abort(.unauthorized)
4044
}
4145
}
@@ -44,7 +48,7 @@ public extension AdminPanelUserType {
4448
public extension AdminPanelUserRoleType {
4549
public static var sidebarMenuPathGenerator: SidebarMenuPathGenerator<Self> {
4650
return { role in
47-
role.menuPath
51+
role?.menuPath ?? ""
4852
}
4953
}
5054
}

Sources/AdminPanel/Providers/AdminPanelProvider.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ public final class AdminPanelProvider<U: AdminPanelUserType>: Provider {
135135
"adminpanel:config": AdminPanelConfigTag<U>(),
136136
"adminpanel:sidebar:heading": SidebarHeadingTag(),
137137
"adminpanel:sidebar:menuitem": SidebarMenuItemTag(),
138-
"adminpanel:user": UserTag()
138+
"adminpanel:user": UserTag(),
139+
"adminpanel:user:requireRole": RequireRoleTag<U>()
139140
])
140141

141142
return .done(on: container)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Leaf
2+
import Authentication
3+
import Sugar
4+
5+
public final class RequireRoleTag<U: AdminPanelUserType>: TagRenderer {
6+
public func render(tag: TagContext) throws -> Future<TemplateData> {
7+
try tag.requireParameterCount(1)
8+
9+
let container = try tag.container.make(
10+
CurrentUserContainer<U>.self
11+
)
12+
13+
let body = try tag.requireBody()
14+
15+
return tag.serializer.serialize(ast: body).map(to: TemplateData.self) { body in
16+
guard
17+
let roleString: String = tag.parameters[0].string,
18+
let requiredRole = U.Role.init(roleString)
19+
else {
20+
throw tag.error(reason: "Invalid role requirement")
21+
}
22+
23+
// User is either not logged in or not allowed to see content
24+
guard
25+
let userRole = container.user?.role,
26+
userRole >= requiredRole
27+
else {
28+
return TemplateData.string("")
29+
}
30+
31+
let parsedBody = String(data: body.data, encoding: .utf8) ?? ""
32+
return .string(parsedBody)
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)