diff --git a/Package.resolved b/Package.resolved index be5f298..d0ec225 100644 --- a/Package.resolved +++ b/Package.resolved @@ -54,6 +54,24 @@ "version" : "2.8.0" } }, + { + "identity" : "jwt", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/jwt.git", + "state" : { + "revision" : "d65f32bfd08fae5910d603028be5dec4f35b3482", + "version" : "4.2.2" + } + }, + { + "identity" : "jwt-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/jwt-kit.git", + "state" : { + "revision" : "e05513b5aec24f88012b6e3034115b6bc915356a", + "version" : "4.13.2" + } + }, { "identity" : "multipart-kit", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index fd79d3d..c1b30ce 100644 --- a/Package.swift +++ b/Package.swift @@ -13,6 +13,7 @@ let package = Package( .package(url: "https://github.com/vapor/fluent.git", from: "4.9.0"), // 🐘 Fluent driver for Postgres. .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.8.0"), + .package(url: "https://github.com/vapor/jwt.git", from: "4.0.0-rc.1"), ], targets: [ .executableTarget( @@ -21,6 +22,7 @@ let package = Package( .product(name: "Fluent", package: "fluent"), .product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"), .product(name: "Vapor", package: "vapor"), + .product(name: "JWT", package: "jwt"), ], swiftSettings: swiftSettings ), diff --git a/Sources/App/Controllers/cntrlAssociate.swift b/Sources/App/Controllers/cntrlAssociate.swift index f157b82..fa326a8 100644 --- a/Sources/App/Controllers/cntrlAssociate.swift +++ b/Sources/App/Controllers/cntrlAssociate.swift @@ -23,9 +23,10 @@ struct cntrlAssociate: RouteCollection { @Sendable func index(req: Request) async throws -> Response { - guard let obj = try? await mdlAssociate.ObjQuery(req: req).all() else { - throw Abort(.badGateway, reason: "Something went wrong with this api.") - } + let obj = try await mdlAssociate.ObjQuery(req: req).all() +// guard let obj = try? await mdlAssociate.ObjQuery(req: req).all() else { +// throw Abort(.badGateway, reason: "Something went wrong with this api.") +// } guard let response = try? await obj.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Array could not be shown.") } diff --git a/Sources/App/Controllers/cntrlJWT.swift b/Sources/App/Controllers/cntrlJWT.swift index 14fe8e8..f839460 100644 --- a/Sources/App/Controllers/cntrlJWT.swift +++ b/Sources/App/Controllers/cntrlJWT.swift @@ -5,4 +5,15 @@ // Created by Michiel Carman on 4/13/24. // -import Foundation + +import Fluent +import Vapor + +struct cntrlJWT: RouteCollection{ + func boot(routes: Vapor.RoutesBuilder) throws { + let rts = routes.grouped("jwt") + rts.get{req in + try req.jwt.sign(mdlJWT(result: "test"), kid: .private) + } + } +} diff --git a/Sources/App/Migrations/AllMigrations.swift b/Sources/App/Migrations/AllMigrations.swift index 1d916e6..d027d37 100644 --- a/Sources/App/Migrations/AllMigrations.swift +++ b/Sources/App/Migrations/AllMigrations.swift @@ -19,6 +19,7 @@ public func doMigrations(_ app: Application) async throws{ app.migrations.add(mdlDocument.Create()) app.migrations.add(mdlXAssocDept.Create()) app.migrations.add(mdlXDocDept.Create()) + app.migrations.add(mdlDocument.tmpField()) try await app.autoMigrate() } diff --git a/Sources/App/Models/mdlDepartment.swift b/Sources/App/Models/mdlDepartment.swift index 6eb52ba..f8a4cf6 100644 --- a/Sources/App/Models/mdlDepartment.swift +++ b/Sources/App/Models/mdlDepartment.swift @@ -17,7 +17,7 @@ final class mdlDepartment: Model, Content { @ID(custom: "id", generatedBy: .database) var id: Int? @Field(key: "name") var name: String? - @OptionalParent(key: "parentId") var parent: mdlDepartment? + @OptionalParent(key: "departmentId") var parent: mdlDepartment? @Children(for: \.$parent) var subdepartments: [mdlDepartment] @Siblings(through: mdlXAssocDept.self, from: \.$department, to: \.$associate) var associates: [mdlAssociate] diff --git a/Sources/App/Models/mdlDocument.swift b/Sources/App/Models/mdlDocument.swift index 7156094..8e6d473 100644 --- a/Sources/App/Models/mdlDocument.swift +++ b/Sources/App/Models/mdlDocument.swift @@ -18,7 +18,7 @@ final class mdlDocument: Model, Content { @Field(key: "name") var name: String? @Field(key: "number") var number: String? - @Parent(key: "docTypeId") var doctype: mdlDocType + @OptionalParent(key: "docTypeId") var doctype: mdlDocType? @Parent(key: "departmentId") var department: mdlDepartment @OptionalParent(key: "parentId") var parent: mdlDocument? @Children(for: \.$parent) var subsequent: [mdlDocument] @@ -33,7 +33,7 @@ final class mdlDocument: Model, Content { init(id: Int? = nil, name: String? = nil, number: String? = nil, - doctypeid: Int, + doctypeid: Int? = nil, departmentid: Int, parentid: Int? = nil, createuserid: Int? = nil, @@ -42,7 +42,7 @@ final class mdlDocument: Model, Content { self.id = id self.name = name self.number = number - self.$doctype.$id.value = doctypeid + if(doctypeid != nil) { self.$doctype.$id.value = doctypeid } self.$department.$id.value = departmentid if(parentid != nil) { self.$parent.$id.value = parentid } self.createuserid = createuserid @@ -70,6 +70,19 @@ extension mdlDocument{ try await database.schema("document").delete() } } + struct tmpField: AsyncMigration { + func prepare(on database: Database) async throws { + try await database.schema("document") + .field("dept", .string) + .update() + } + + func revert(on database: Database) async throws { + try await database.schema("document") + .deleteField("dept") + .update() + } + } public static func ObjQuery(req: Request) async throws -> QueryBuilder{ let query = mdlDocument.query(on: req.db) diff --git a/Sources/App/Models/mdlJWT.swift b/Sources/App/Models/mdlJWT.swift index 14fe8e8..0217226 100644 --- a/Sources/App/Models/mdlJWT.swift +++ b/Sources/App/Models/mdlJWT.swift @@ -5,4 +5,10 @@ // Created by Michiel Carman on 4/13/24. // -import Foundation +import Vapor +import JWT + +struct mdlJWT: JWTPayload{ + var result: String + func verify(using signer: JWTKit.JWTSigner) {} +} diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index 76cf967..b24fc25 100644 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -2,9 +2,29 @@ import NIOSSL import Fluent import FluentPostgresDriver import Vapor +import JWT + +extension String { + var bytes: [UInt8] { .init(self.utf8) } +} + +extension JWKIdentifier { + static let `public` = JWKIdentifier(string: "public") + static let `private` = JWKIdentifier(string: "private") +} // configures your application public func configure(_ app: Application) async throws { + + let privateKey = try String(contentsOfFile: app.directory.workingDirectory + "jwtRS256.key") + let privateSigner = try JWTSigner.rs256(key: .private(pem: privateKey.bytes)) + + let publicKey = try String(contentsOfFile: app.directory.workingDirectory + "jwtRS256.key.pub") + let publicSigner = try JWTSigner.rs256(key: .public(pem: publicKey.bytes)) + + app.jwt.signers.use(privateSigner, kid: .private) + app.jwt.signers.use(publicSigner, kid: .public, isDefault: true) + app.middleware.use(CORSMiddleware()) let corsConfiguration = CORSMiddleware.Configuration( allowedOrigin: .all, diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index b9a5c5a..a857f1c 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -11,4 +11,6 @@ func routes(_ app: Application) throws { baseApp.get { req async in "Training Services Version 1.0" } + try baseApp.register(collection: cntrlAssociate()) + try baseApp.register(collection: cntrlDepartment()) } diff --git a/jwtRS256.key b/jwtRS256.key new file mode 100644 index 0000000..14183d0 --- /dev/null +++ b/jwtRS256.key @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,8302B108E3C2CB279C4FF6742ECEC521 + +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 +-----END RSA PRIVATE KEY----- diff --git a/jwtRS256.key.pub b/jwtRS256.key.pub new file mode 100644 index 0000000..02bd6fb --- /dev/null +++ b/jwtRS256.key.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsJ60y2SCZXKsXh+pGSrc +z/wXwt4O39jpBnTh9irvDg4PQD9z+FLp0Iy0s5tq7VNXr8+77zOVgiiIIKWOIukC +hWztueEfM5tQ/9SEblHVN/s1ZyT7ESY+pZJY0lTiPVQ49nEmigNGXA7HCt+pXU0k +/PhSLjX1MJ5MoexZ+8WvSs9VDOnJxfwfw5qU+ATAJHm64ijD0hPOcErlBppZZuo/ +7Y9RrNF1BXQxtqSIzZI4U+ndCXcjYB2w7JcfwrpQJji+EBbO9rO0OYLdP0LTAVWW +uDPt4JRA72sbYjBvvBejZcK5ssKO2RNi8xfI3bnXzyhIHdjlDhVs6q6ukr7LSLr6 +rFMvyedz28gfMf5Bs7MlzUi9itLIGtpIPjXAqDMa49CHJtZj59yXBl9deO+yv8AU +75MpnlnjaQkns2V76zVyX/TcLunZd3jsLs6KWr4Kw6nUTsnfRxPgYYL2uSZ9wrZ/ +YhzJjx8tevzn4dC+JDEKP2iVZ9P7wUOfZsVVj1ICFkDt1yM4Wlh5oBtqdZZR/HJc +XgzAxUNMX9dkJUM7xzDA6Dc9UchvdHw+vYne5ROoepZHegmZiLveUET321RHsaEh +Mmoct4xmgVkGrhakQLPTAjDL1Vw3qHUr8nObF5rxTikR5SrhBX00cjRNcheyLd3u +O/pxZKD+UMAwwrmVAyFkTj8CAwEAAQ== +-----END PUBLIC KEY-----