Skip to content

Commit

Permalink
Refactor id and reg no, create posts model
Browse files Browse the repository at this point in the history
  • Loading branch information
BoogieMonster1O1 committed Jan 5, 2024
1 parent 63949a6 commit 452e725
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 55 deletions.
16 changes: 8 additions & 8 deletions Sources/App/Controllers/Auth/GoogleController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct GoogleController: RouteCollection {
}
}

return try await generateTokenPairResponse(req: req, id: user.requireID())
return try await generateTokenPairResponse(req: req, collegeId: user.requireID())
}

func linkGoogleAccount(req: Request) async throws -> GoogleLinkSuccess {
Expand All @@ -77,8 +77,14 @@ struct GoogleController: RouteCollection {

let identityToken = try req.jwt.verify(idTokenString, as: IdentityToken.self)

let user = try await RegisteredUser.query(on: req.db)
.filter(\.$id == identityToken.id)
.first()
.unwrap(orError: Abort(.notFound, reason: "User not registered"))
.get()

let userCred: UserCredentials = try await UserCredentials.query(on: req.db)
.filter(\.$id == identityToken.id.value)
.filter(\.$id == user.$collegeId.id)
.first()
.unwrap(orError: Abort(.notFound, reason: "User not registered"))
.get()
Expand All @@ -87,12 +93,6 @@ struct GoogleController: RouteCollection {
throw Abort(.forbidden, reason: "Google account already linked")
}

let user: UnregisteredUser = try await UnregisteredUser.query(on: req.db)
.filter(\.$id == identityToken.id.value)
.first()
.unwrap(orError: Abort(.notFound, reason: "User does not exist"))
.get()

if user.email.lowercased() != email.lowercased() {
throw Abort(.badRequest, reason: "Email mismatch")
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/App/Controllers/Auth/LoginController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct LoginController: RouteCollection {
}

if try await authUserWithPassword(req: req, args: params) {
return try await generateTokenPairResponse(req: req, id: params.id)
return try await generateTokenPairResponse(req: req, collegeId: params.id)
} else {
throw Abort(.badRequest, reason: "Invalid credentials")
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/App/Controllers/Auth/SignupController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct SignupController: RouteCollection {
.unwrap(or: Abort(.notFound, reason: "User does not exist"))
.get()

if await (try RegisteredUser.query(on: req.db).filter(\.$id == args.id).first() != nil) {
if await (try RegisteredUser.query(on: req.db).filter(\.$collegeId.$id == args.id).first() != nil) {
throw Abort(.conflict, reason: "User already exists")
}

Expand Down Expand Up @@ -155,7 +155,7 @@ struct SignupController: RouteCollection {
throw Abort(.internalServerError, reason: "Database error")
}

return try await generateTokenPairResponse(req: req, id: payload.id)
return try await generateTokenPairResponse(req: req, collegeId: payload.id)
}

@inlinable
Expand Down
12 changes: 6 additions & 6 deletions Sources/App/GraphQL/Resolver+Mutation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Graphiti
import Fluent

struct EditUserInfoArgs: Codable {
var regNo: Int
var id: Int
var gender: String?
var bio: String?
var pronouns: String?
Expand All @@ -21,17 +21,17 @@ extension Resolver {
func editUserInfo(request: Request, arguments: EditUserInfoArgs) async throws -> RegisteredUser {
let token = try await getAndVerifyAccessToken(req: request)

if token.regNo == arguments.regNo {
if token.id == arguments.id {
try await assertPermission(request: request, .editProfile)
} else if (!token.regNo.hasPermission(.admin)) {
request.logger.error("User \(token.regNo) tried to edit user info of \(arguments.regNo)")
} else if (!token.perm.hasPermission(.admin)) {
request.logger.error("User \(token.id) tried to edit user info of \(arguments.id)")
throw Abort(.forbidden, reason: "Mismatch in registration number")
}

guard let user = try await RegisteredUser.query(on: request.db)
.filter(\.$regNo == arguments.regNo)
.filter(\.$id == arguments.id)
.first() else {
throw Abort(.notFound, reason: "User \(arguments.regNo) not found")
throw Abort(.notFound, reason: "User \(arguments.id) not found")
}

user.setValue(\.gender, arguments.gender, orElse: "X")
Expand Down
4 changes: 2 additions & 2 deletions Sources/App/GraphQL/Resolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Fluent
import Vapor

struct GetRegisteredUserArgs: Codable {
let regNo: Int
let id: Int
}

final class Resolver {
Expand Down Expand Up @@ -39,7 +39,7 @@ final class Resolver {
func getRegisteredUser(request: Request, arguments: GetRegisteredUserArgs) async throws -> RegisteredUser {
try await assertPermission(request: request, .identity)
return try await RegisteredUser.query(on: request.db)
.filter(\.$regNo == arguments.regNo)
.filter(\.$id == arguments.id)
.first()
.unwrap(or: Abort(.notFound))
.get()
Expand Down
6 changes: 3 additions & 3 deletions Sources/App/GraphQL/Schema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let schema = try! Schema<Resolver, Request> {
Scalar(Date.self)

Type(UnregisteredUser.self) {
Field("id", at: \.id)
Field("collegeId", at: \.id)
Field("name", at: \.name)
Field("phone", at: \.phone)
Field("email", at: \.email)
Expand All @@ -25,7 +25,7 @@ let schema = try! Schema<Resolver, Request> {
}

Type(RegisteredUser.self) {
Field("id", at: \.id)
Field("collegeId", at: \.id)
Field("name", at: \.name)
Field("phone", at: \.phone)
Field("email", at: \.email)
Expand All @@ -46,7 +46,7 @@ let schema = try! Schema<Resolver, Request> {

Field("users", at: Resolver.getAllRegisteredUsers)
Field("user", at: Resolver.getRegisteredUser) {
Argument("regNo", at: \.regNo)
Argument("id", at: \.id)
}
}

Expand Down
6 changes: 3 additions & 3 deletions Sources/App/Migrations/002_CreateRegisteredUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Fluent
struct CreateRegisteredUser: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema("registeredUsers")
.field("id", .string, .required)
.field("collegeId", .string, .required, .references("users", "id"))
.field("name", .string, .required)
.field("phone", .string, .required)
.field("email", .string, .required)
Expand All @@ -21,8 +21,8 @@ struct CreateRegisteredUser: Migration {
.field("date_registered", .datetime, .required)
.field("bio", .string)
.field("intake_year", .int, .required)
.field("reg_no", .int, .custom("GENERATED ALWAYS AS IDENTITY"))
.unique(on: "id")
.field("id", .int, .custom("GENERATED ALWAYS AS IDENTITY"))
.unique(on: "collegeId")
.unique(on: "email")
.create()
}
Expand Down
25 changes: 25 additions & 0 deletions Sources/App/Migrations/004_CreatePosts.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// 004_CreatePosts.swift
//
//
// Created by Shrish Deshpande on 05/01/24.
//

import Fluent

struct CreatePosts: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema("posts")
.field("id", .string, .required)
.field("user", .int, .required, .references("registeredUsers", "regNo"))
.field("content", .string, .required)
.field("created_at", .datetime, .required)
.field("deleted", .bool, .required)
.unique(on: "id")
.create()
}

func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema("posts").delete()
}
}
36 changes: 16 additions & 20 deletions Sources/App/Models/Content/IdentityToken.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,33 @@ import Fluent

open class IdentityToken: JWTPayload {
enum CodingKeys: String, CodingKey {
case id = "sub"
case regNo = "rgn"
case id = "rgn"
case expiration = "exp"
case token = "tkn"
case perm = "perm"
case issuer = "iss"
}

public init(id: String, regNo: Int) {
public init(id: Int) {
self.expiration = .init(value: .init(timeIntervalSinceNow: 86400))
self.id = .init(stringLiteral: id)
self.token = [UInt8].random(count: 64).base64
self.perm = Permissions.create([.identity, .editProfile])
self.regNo = regNo
self.id = id
}

public convenience init(req: Request, id userId: String) async throws {
public convenience init(req: Request, collegeId userId: String) async throws {
let user: RegisteredUser? = try await RegisteredUser.query(on: req.db)
.filter(\.$id == userId)
.filter(\.$collegeId.$id == userId)
.first()
guard let regNo = user?.regNo else {
guard let id = user?.id else {
req.logger.error("Tried creating access token for non existant user '\(userId)'")
throw Abort(.notFound)
}

self.init(id: userId, regNo: regNo)
self.init(id: id)
}

public var id: SubjectClaim

public var regNo: Int
public var id: Int

public var expiration: ExpirationClaim

Expand Down Expand Up @@ -85,7 +81,7 @@ func refreshAccessToken(req: Request) async throws -> (IdentityToken, String) {
try await blacklistToken(req: req, token: oldToken)
let body = try req.content.decode(RefreshTokenRequest.self)
guard let realToken = try await req.redis.get(.init(stringLiteral: body.refreshToken), as: String.self).get() else {
req.logger.error("User '\(oldToken.id)' tried to refresh with a nonexistant token!")
req.logger.error("User '\(oldToken.id )' tried to refresh with a nonexistant token!")
throw Abort(.badRequest, reason: "Invalid refresh token")
}

Expand Down Expand Up @@ -120,21 +116,21 @@ func getAndVerifyAccessToken(req: Request) async throws -> IdentityToken {
return payload
}

func generateTokenPairResponse(req: Request, id: String) async throws -> AuthResponseBody {
let tokenPair = try await generateStoredTokenPair(req: req, id: id)
func generateTokenPairResponse(req: Request, collegeId: String) async throws -> AuthResponseBody {
let tokenPair = try await generateStoredTokenPair(req: req, collegeId: collegeId)
let expiresAt = Int64(tokenPair.0.expiration.value.timeIntervalSince1970 * 1000)
return .init(accessToken: try req.jwt.sign(tokenPair.0), refreshToken: tokenPair.1, expiresAt: expiresAt)
}

func generateStoredTokenPair(req: Request, id: String) async throws -> (IdentityToken, String) {
let tokenPair = try await generateTokenPair(req: req, id: id)
func generateStoredTokenPair(req: Request, collegeId: String) async throws -> (IdentityToken, String) {
let tokenPair = try await generateTokenPair(req: req, collegeId: collegeId)
try await req.redis.set(.init(stringLiteral: tokenPair.1), to: tokenPair.0.token).get()
return tokenPair
}

@inlinable
func generateTokenPair(req: Request, id: String) async throws -> (IdentityToken, String) {
return (try await IdentityToken(req: req, id: id), [UInt8].random(count: 64).base64)
func generateTokenPair(req: Request, collegeId: String) async throws -> (IdentityToken, String) {
return (try await IdentityToken(req: req, collegeId: collegeId), [UInt8].random(count: 64).base64)
}

func generateStoredTokenPair(req: Request, previous: IdentityToken) async throws -> (IdentityToken, String) {
Expand All @@ -145,5 +141,5 @@ func generateStoredTokenPair(req: Request, previous: IdentityToken) async throws

@inlinable
func generateTokenPair(previous: some IdentityToken) async throws -> (IdentityToken, String) {
return (IdentityToken(id: previous.id.value, regNo: previous.regNo), [UInt8].random(count: 64).base64)
return (IdentityToken(id: previous.id), [UInt8].random(count: 64).base64)
}
2 changes: 1 addition & 1 deletion Sources/App/Models/InitialRegisteredUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Fluent
final class InitialRegisteredUser: Model, Content {
static let schema = "registeredUsers"

@ID(custom: "id", generatedBy: .user)
@ID(custom: "collegeId", generatedBy: .user)
var id: String?

@Field(key: "name")
Expand Down
39 changes: 39 additions & 0 deletions Sources/App/Models/Post.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Post.swift
//
//
// Created by Shrish Deshpande on 05/01/24.
//

import Vapor
import Fluent

final class Post: Model, Content {
public static let schema = "posts"

@ID(custom: "id", generatedBy: .user)
var id: String?

@Field(key: "user")
var user: Int

@Field(key: "content")
var content: String

@Timestamp(key: "created_at", on: .create)
var createdAt: Date?

@Field(key: "deleted")
var deleted: Bool

init() {
}

// TODO: attachments (media), comments enabled, edited
init(id: String, regNo user: Int, content: String) {
self.id = id
self.user = user
self.content = content
self.deleted = false
}
}
14 changes: 7 additions & 7 deletions Sources/App/Models/RegisteredUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public final class RegisteredUser: Model, Content {
public static let schema = "registeredUsers"

@ID(custom: "id", generatedBy: .user)
public var id: String?
public var id: Int?

@Parent(key: "collegeId")
var collegeId: UnregisteredUser

@Field(key: "name")
var name: String
Expand Down Expand Up @@ -43,14 +46,11 @@ public final class RegisteredUser: Model, Content {

@Field(key: "intake_year")
var intakeYear: Int

@Field(key: "reg_no")
var regNo: Int?

public init() { }

public init(id: String, name: String, phone: String, email: String, personalEmail: String? = nil, branch: String, gender: String, pronouns: String? = nil, bio: String? = nil, intakeYear: Int, regNo: Int? = nil) {
self.id = id
public init(collegeId: String, name: String, phone: String, email: String, personalEmail: String? = nil, branch: String, gender: String, pronouns: String? = nil, bio: String? = nil, intakeYear: Int, id: Int? = nil) {
self.$collegeId.id = collegeId
self.name = name
self.phone = phone
self.email = email
Expand All @@ -60,6 +60,6 @@ public final class RegisteredUser: Model, Content {
self.pronouns = pronouns
self.bio = bio
self.intakeYear = intakeYear
self.regNo = regNo
self.id = id
}
}
2 changes: 0 additions & 2 deletions Sources/App/Models/UnregisteredUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,4 @@ final class UnregisteredUser: Model, Content {
self.branch = branch
self.gender = gender
}


}

0 comments on commit 452e725

Please sign in to comment.