Initial commit

This commit is contained in:
Johan
2026-01-26 00:37:35 +01:00
commit f303cb46b7
30 changed files with 2251 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
//
// ArticleModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class ArticleModel: Model, @unchecked Sendable {
static let schema: String = Database.articles.rawValue
// MARK: - ID
@ID(key: .id)
var id: UUID?
// MARK: - CMS Fields (all optional)
@OptionalField(key: FieldKeys.title)
var title: String?
@OptionalField(key: FieldKeys.description)
var description: String?
@OptionalField(key: FieldKeys.slug)
var slug: String?
@OptionalField(key: FieldKeys.excerpt)
var excerpt: String?
@OptionalField(key: FieldKeys.image)
var image: String?
@OptionalEnum(key: FieldKeys.status)
var status: Status?
@OptionalField(key: FieldKeys.authorID)
var authorID: UserModel.IDValue?
@OptionalField(key: FieldKeys.categories)
var categories: [CategoryModel.IDValue]?
@OptionalField(key: FieldKeys.tags)
var tags: [TagModel.IDValue]?
// MARK: - Timestamps
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
@OptionalField(key: FieldKeys.publishDate)
var publishDate: Date?
// MARK: - Initializer
init() {}
}
extension ArticleModel {
struct FieldKeys {
static var title: FieldKey { "title" }
static var description: FieldKey { "description" }
static var slug: FieldKey { "slug" }
static var excerpt: FieldKey { "excerpt" }
static var image: FieldKey { "image" }
static var status: FieldKey { "status" }
static var authorID: FieldKey { "authorID" }
static var categories: FieldKey { "categories" }
static var tags: FieldKey { "tags" }
static var createdAt: FieldKey { "createdAt" }
static var updatedAt: FieldKey { "updatedAt" }
static var publishDate: FieldKey { "publishDate" }
}
}
import Fluent
extension ArticleModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(ArticleModel.schema)
.id()
.field(FieldKeys.title, .string)
.field(FieldKeys.description, .string)
.field(FieldKeys.slug, .string)
.field(FieldKeys.excerpt, .string)
.field(FieldKeys.image, .string)
.field(FieldKeys.status, .string)
.field(FieldKeys.authorID, .uuid)
.field(FieldKeys.categories, .array(of: .uuid))
.field(FieldKeys.tags, .array(of: .uuid))
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.field(FieldKeys.publishDate, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(ArticleModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,107 @@
//
// CampusModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class CampusModel: Model, @unchecked Sendable {
static let schema: String = Database.campuses.rawValue
// MARK: - ID
@ID(key: .id)
var id: UUID?
// MARK: - Data
@OptionalField(key: FieldKeys.title)
var title: String?
@OptionalField(key: FieldKeys.description)
var description: String?
@OptionalField(key: FieldKeys.slug)
var slug: String?
@OptionalField(key: FieldKeys.content)
var content: String?
@Enum(key: FieldKeys.status)
var status: Status
@Field(key: FieldKeys.instructorID)
var instructorID: UserModel.IDValue
@OptionalField(key: FieldKeys.price)
var price: Double?
@OptionalField(key: FieldKeys.tags)
var tags: [TagModel.IDValue]?
@OptionalField(key: FieldKeys.categories)
var categories: [CategoryModel.IDValue]?
// MARK: - Timestamps
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
@Field(key: FieldKeys.publishDate)
var publishDate: Date?
// MARK: - Initializers
init() {}
}
extension CampusModel {
struct FieldKeys {
static var title: FieldKey { "title" }
static var description: FieldKey { "description" }
static var slug: FieldKey {"slug"}
static var content: FieldKey { "content" }
static var status: FieldKey { "status" }
static var instructorID: FieldKey { "instructorID" }
static var price: FieldKey { "price" }
static var tags: FieldKey { "tags" }
static var categories: FieldKey { "categories" }
static var createdAt: FieldKey { "createdAt" }
static var updatedAt: FieldKey { "updatedAt" }
static var publishDate: FieldKey { "publishDate" }
}
}
import Fluent
extension CampusModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(CampusModel.schema)
.id()
.field(FieldKeys.title, .string)
.field(FieldKeys.description, .string)
.field(FieldKeys.slug, .string)
.field(FieldKeys.content, .string)
.field(FieldKeys.status, .string, .required)
.field(FieldKeys.instructorID, .uuid, .required)
.field(FieldKeys.price, .double)
.field(FieldKeys.tags, .array(of: .uuid))
.field(FieldKeys.categories, .array(of: .uuid))
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.field(FieldKeys.publishDate, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(CampusModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,57 @@
//
// CategoryModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class CategoryModel: Model, @unchecked Sendable {
static let schema: String = Database.categories.rawValue
// MARK: - ID
@ID(key: .id)
var id: UUID?
// MARK: - Data
@Field(key: FieldKeys.name)
var name: String
// MARK: - Initializers
init() {}
init(
id: UUID? = nil,
name: String
) {
self.id = id
self.name = name
}
}
extension CategoryModel {
struct FieldKeys {
static var name: FieldKey { "name" }
}
}
extension CategoryModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(CategoryModel.schema)
.id()
.field(FieldKeys.name, .string, .required)
.unique(on: FieldKeys.name)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(CategoryModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,78 @@
//
// ConfirmationModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
import Vapor
import Fluent
final class ConfirmationModel: Model, @unchecked Sendable {
static let schema: String = Database.confirmations.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.userID)
var userID: UserModel.IDValue
@Field(key: FieldKeys.confirmationCode)
var confirmationCode: String
@Field(key: FieldKeys.email)
var email: String
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.validTill, on: .none)
var validTill: Date?
@Field(key: FieldKeys.isConfirmed)
var isConfirmed: Bool
init() {}
init(id: UUID? = nil, userID: UserModel.IDValue, email: String?, confirmationCode: String, validTill: Date, isConfirmed: Bool = false) {
self.id = id
self.userID = userID
self.confirmationCode = confirmationCode
self.validTill = validTill
self.isConfirmed = isConfirmed
}
}
extension ConfirmationModel {
struct FieldKeys {
static var userID: FieldKey { "userID" }
static var confirmationCode: FieldKey { "confirmationCode" }
static var email: FieldKey { "email" }
static var createdAt: FieldKey { "createdAt" }
static var validTill: FieldKey { "validTill" }
static var isConfirmed: FieldKey { "isConfirmed" }
}
}
extension ConfirmationModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(ConfirmationModel.schema)
.id()
.field(FieldKeys.userID, .uuid, .required)
.field(FieldKeys.confirmationCode, .string, .required)
.field(FieldKeys.email, .string, .required)
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.validTill, .datetime)
.field(FieldKeys.isConfirmed, .bool, .required)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(ConfirmationModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,103 @@
//
// CourseModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class CourseModel: Model, @unchecked Sendable {
static let schema: String = Database.courses.rawValue
// MARK: - ID
@ID(key: .id)
var id: UUID?
// MARK: - Data
@OptionalField(key: FieldKeys.title)
var title: String?
@OptionalField(key: FieldKeys.description)
var description: String?
@OptionalField(key: FieldKeys.slug)
var slug: String?
@OptionalField(key: FieldKeys.excerpt)
var excerpt: String?
@OptionalField(key: FieldKeys.content)
var content: String?
@OptionalField(key: FieldKeys.campusID)
var campusID: CampusModel.IDValue?
@Field(key: FieldKeys.authorID)
var authorID: UserModel.IDValue
@OptionalField(key: FieldKeys.image)
var image: String?
@Enum(key: FieldKeys.status)
var status: Status
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
@OptionalField(key: FieldKeys.publishDate)
var publishDate: Date?
// MARK: - Initializers
init() {}
}
extension CourseModel {
struct FieldKeys {
static var title: FieldKey { "title" }
static var description: FieldKey { "description" }
static var slug: FieldKey { "slug" }
static var excerpt: FieldKey { "excerpt" }
static var content: FieldKey { "content" }
static var campusID: FieldKey { "campusID" }
static var authorID: FieldKey { "authorID" }
static var image: FieldKey { "image" }
static var status: FieldKey { "status" }
static var createdAt: FieldKey { "createdAt" }
static var updatedAt: FieldKey { "updatedAt" }
static var publishDate: FieldKey { "publishDate" }
}
}
extension CourseModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(CourseModel.schema)
.id()
.field(FieldKeys.title, .string)
.field(FieldKeys.description, .string)
.field(FieldKeys.slug, .string)
.field(FieldKeys.excerpt, .string)
.field(FieldKeys.content, .string)
.field(FieldKeys.campusID, .uuid)
.field(FieldKeys.authorID, .uuid, .required)
.field(FieldKeys.image, .string)
.field(FieldKeys.status, .string, .required)
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.field(FieldKeys.publishDate, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(CourseModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,79 @@
//
// FileModel.swift
// ExodaiAcademy
//
// Created by Exodai on 24/01/2026.
//
import Fluent
final class FileModel: Model, @unchecked Sendable {
static let schema: String = Database.files.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.folderID)
var folderID: FolderModel.IDValue
@Field(key: FieldKeys.name)
var name: String
@Field(key: FieldKeys.type)
var type: String
@Field(key: FieldKeys.mimeType)
var mimeType: String
@Field(key: FieldKeys.storageKey)
var storageKey: String
@Field(key: FieldKeys.size)
var size: Int64
@OptionalField(key: FieldKeys.metadata)
var metadata: String?
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
init() {}
}
extension FileModel {
struct FieldKeys {
static var folderID: FieldKey { "folderID" }
static var name: FieldKey { "name" }
static var type: FieldKey { "type" }
static var mimeType: FieldKey { "mimeType" }
static var storageKey: FieldKey { "storageKey" }
static var size: FieldKey { "size" }
static var metadata: FieldKey { "metadata" }
static var createdAt: FieldKey { "createdAt" }
}
}
import Fluent
extension FileModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(FileModel.schema)
.id()
.field(FieldKeys.folderID, .uuid, .required)
.field(FieldKeys.name, .string, .required)
.field(FieldKeys.type, .string, .required)
.field(FieldKeys.mimeType, .string, .required)
.field(FieldKeys.storageKey, .string, .required)
.field(FieldKeys.size, .int64, .required)
.field(FieldKeys.metadata, .string)
.field(FieldKeys.createdAt, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(FileModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,59 @@
//
// FolderModel.swift
// ExodaiAcademy
//
// Created by Exodai on 24/01/2026.
//
import Fluent
final class FolderModel: Model, @unchecked Sendable {
static let schema: String = Database.folders.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.name)
var name: String
@OptionalField(key: FieldKeys.parentFolderID)
var parentFolderID: FolderModel.IDValue?
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
init() {}
}
extension FolderModel {
struct FieldKeys {
static var name: FieldKey { "name" }
static var parentFolderID: FieldKey { "parentFolderID" }
static var createdAt: FieldKey { "createdAt" }
static var updatedAt: FieldKey { "updatedAt" }
}
}
import Fluent
extension FolderModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(FolderModel.schema)
.id()
.field(FieldKeys.name, .string, .required)
.field(FieldKeys.parentFolderID, .uuid)
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(FolderModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,72 @@
//
// LogModel.swift
// ExodaiAcademy
//
// Created by Exodai on 24/01/2026.
//
import Fluent
final class LogModel: Model, @unchecked Sendable {
static let schema: String = Database.logs.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.event)
var event: String
@OptionalField(key: FieldKeys.actorID)
var actorID: UserModel.IDValue?
@OptionalField(key: FieldKeys.targetType)
var targetType: String?
@OptionalField(key: FieldKeys.targetID)
var targetID: UUID?
@OptionalField(key: FieldKeys.context)
var context: String?
@OptionalField(key: FieldKeys.ipAddress)
var ipAddress: String?
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
init() {}
}
extension LogModel {
struct FieldKeys {
static var event: FieldKey { "event" }
static var actorID: FieldKey { "actorID" }
static var ipAddress: FieldKey { "ipAddress" }
static var targetType: FieldKey { "targetType" }
static var targetID: FieldKey { "targetID" }
static var context: FieldKey { "context" }
static var createdAt: FieldKey { "createdAt" }
}
}
extension LogModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(LogModel.schema)
.id()
.field(FieldKeys.event, .string, .required)
.field(FieldKeys.actorID, .uuid)
.field(FieldKeys.ipAddress, .string)
.field(FieldKeys.targetType, .string)
.field(FieldKeys.targetID, .uuid)
.field(FieldKeys.context, .string)
.field(FieldKeys.createdAt, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(LogModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,83 @@
//
// PurchaseModel.swift
// ExodaiAcademy
//
// Created by Exodai on 24/01/2026.
//
import Fluent
final class PurchaseModel: Model, @unchecked Sendable {
static let schema: String = Database.purchases.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.userID)
var userID: UserModel.IDValue
@Field(key: FieldKeys.courseID)
var courseID: CourseModel.IDValue
@Field(key: FieldKeys.pricePaid)
var pricePaid: Double
@Field(key: FieldKeys.currency)
var currency: String
@Field(key: FieldKeys.paymentProvider)
var paymentProvider: String
@Field(key: FieldKeys.paymentReference)
var paymentReference: String
@Timestamp(key: FieldKeys.purchasedAt, on: .create)
var purchasedAt: Date?
@OptionalField(key: FieldKeys.refundedAt)
var refundedAt: Date?
@Field(key: FieldKeys.grantedByAdmin)
var grantedByAdmin: Bool
init() {}
}
extension PurchaseModel {
struct FieldKeys {
static var userID: FieldKey { "userID" }
static var courseID: FieldKey { "courseID" }
static var pricePaid: FieldKey { "pricePaid" }
static var currency: FieldKey { "currency" }
static var paymentProvider: FieldKey { "paymentProvider" }
static var paymentReference: FieldKey { "paymentReference" }
static var purchasedAt: FieldKey { "purchasedAt" }
static var refundedAt: FieldKey { "refundedAt" }
static var grantedByAdmin: FieldKey { "grantedByAdmin" }
}
}
extension PurchaseModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(PurchaseModel.schema)
.id()
.field(FieldKeys.userID, .uuid, .required)
.field(FieldKeys.courseID, .uuid, .required)
.field(FieldKeys.pricePaid, .double, .required)
.field(FieldKeys.currency, .string, .required)
.field(FieldKeys.paymentProvider, .string, .required)
.field(FieldKeys.paymentReference, .string, .required)
.field(FieldKeys.purchasedAt, .datetime)
.field(FieldKeys.refundedAt, .datetime)
.field(FieldKeys.grantedByAdmin, .bool, .required)
.unique(on: FieldKeys.userID, FieldKeys.courseID)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(PurchaseModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,100 @@
//
// SessionModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class SessionModel: Model, @unchecked Sendable {
static let schema: String = Database.sessions.rawValue
// MARK: - ID
@ID(key: .id)
var id: UUID?
// MARK: - CMS Fields (ALL optional)
@OptionalField(key: FieldKeys.title)
var title: String?
@OptionalField(key: FieldKeys.description)
var description: String?
@OptionalField(key: FieldKeys.slug)
var slug: String?
@OptionalField(key: FieldKeys.mp4URL)
var mp4URL: String?
@OptionalField(key: FieldKeys.hlsURL)
var hlsURL: String?
@OptionalField(key: FieldKeys.content)
var content: String?
@OptionalEnum(key: FieldKeys.status)
var status: Status?
@OptionalField(key: FieldKeys.courseID)
var courseID: CourseModel.IDValue?
// MARK: - Timestamps
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
@OptionalField(key: FieldKeys.publishDate)
var publishDate: Date?
// MARK: - Initializer
init() {}
}
extension SessionModel {
struct FieldKeys {
static var title: FieldKey { "title" }
static var description: FieldKey { "description" }
static var slug: FieldKey { "slug" }
static var mp4URL: FieldKey { "mp4URL" }
static var hlsURL: FieldKey { "hlsURL" }
static var content: FieldKey { "content" }
static var status: FieldKey { "status" }
static var courseID: FieldKey { "courseID" }
static var createdAt: FieldKey { "createdAt" }
static var updatedAt: FieldKey { "updatedAt" }
static var publishDate: FieldKey { "publishDate" }
}
}
extension SessionModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(SessionModel.schema)
.id()
.field(FieldKeys.title, .string)
.field(FieldKeys.description, .string)
.field(FieldKeys.slug, .string)
.field(FieldKeys.mp4URL, .string)
.field(FieldKeys.hlsURL, .string)
.field(FieldKeys.content, .string)
.field(FieldKeys.status, .string)
.field(FieldKeys.courseID, .uuid)
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.field(FieldKeys.publishDate, .datetime)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(SessionModel.schema).delete()
}
}
}

View File

@@ -0,0 +1,31 @@
//
// TagModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class TagModel: Model, @unchecked Sendable {
static let schema: String = Database.tags.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.name)
var name: String
init() {}
init(id: UUID? = nil, name: String) {
self.id = id
self.name = name
}
}
extension TagModel {
struct FieldKeys {
static var name: FieldKey { "name" }
}
}

View File

@@ -0,0 +1,45 @@
//
// TokenModel.swift
// ExodaiAcademy
//
// Created by Exodai on 23/01/2026.
//
import Fluent
final class TokenModel: Model, @unchecked Sendable {
static let schema: String = Database.tokens.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.userID)
var userID: UserModel.IDValue
@Field(key: FieldKeys.value)
var value: String
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.validTill, on: .none)
var validTill: Date?
init() {}
init(id: UUID? = nil, userID: UserModel.IDValue, value: String, validTill: Date?) {
self.id = id
self.userID = userID
self.value = value
self.validTill = validTill
}
}
extension TokenModel {
struct FieldKeys {
static var userID: FieldKey { "userID" }
static var value: FieldKey { "value" }
static var createdAt: FieldKey { "createdAt" }
static var validTill: FieldKey { "validTill" }
}
}

View File

@@ -0,0 +1,177 @@
//
// UserModel.swift
// ExodaiAcademy
//
// Created by Exodai on 22/01/2026.
//
import Vapor
import Fluent
import FluentKit
final class UserModel: Model, @unchecked Sendable {
static let schema: String = Database.users.rawValue
@ID(key: .id)
var id: UUID?
@Field(key: FieldKeys.username)
var username: String
@Field(key: FieldKeys.email)
var email: String
@Field(key: FieldKeys.password)
var password: String
@Field(key: FieldKeys.role)
var role: Role
@OptionalField(key: FieldKeys.name)
var name: String?
@OptionalField(key: FieldKeys.lastname)
var lastname: String?
@OptionalField(key: FieldKeys.address)
var address: String?
@OptionalField(key: FieldKeys.zipCode)
var zipCode: String?
@OptionalField(key: FieldKeys.city)
var city: String?
@OptionalEnum(key: FieldKeys.country)
var Country: CountryCode?
@OptionalField(key: FieldKeys.stripeID)
var stripeID: String?
@Timestamp(key: FieldKeys.createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: FieldKeys.updatedAt, on: .update)
var updatedAt: Date?
@Timestamp(key: FieldKeys.deletedAt, on: .delete)
var deletedAt: Date?
@Timestamp(key: FieldKeys.lastLogin, on: .none)
var lastLogin: Date?
init() {
}
init(id: UUID? = nil, username: String, email: String, password: String, role: Role) {
self.id = id
self.username = username
self.email = email
self.password = password
self.role = role
}
}
extension UserModel {
struct FieldKeys {
static var username: FieldKey {"username"}
static var email: FieldKey {"email"}
static var password: FieldKey {"password"}
static var role: FieldKey {"role"}
static var name: FieldKey {"name"}
static var lastname: FieldKey {"lastname"}
static var address: FieldKey {"address"}
static var zipCode: FieldKey {"zipCode"}
static var city: FieldKey {"city"}
static var country: FieldKey {"country"}
static var stripeID: FieldKey {"stripeID"}
static var createdAt: FieldKey {"createdAt"}
static var updatedAt: FieldKey {"updatedAt"}
static var deletedAt: FieldKey {"deletedAt"}
static var lastLogin: FieldKey {"lastLogin"}
}
}
import Fluent
extension UserModel {
struct Migration: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(UserModel.schema)
.id()
.field(FieldKeys.username, .string, .required)
.field(FieldKeys.email, .string, .required)
.field(FieldKeys.password, .string, .required)
.field(FieldKeys.role, .string, .required)
.field(FieldKeys.name, .string)
.field(FieldKeys.lastname, .string)
.field(FieldKeys.address, .string)
.field(FieldKeys.zipCode, .string)
.field(FieldKeys.city, .string)
.field(FieldKeys.country, .string)
.field(FieldKeys.stripeID, .string)
.field(FieldKeys.createdAt, .datetime)
.field(FieldKeys.updatedAt, .datetime)
.field(FieldKeys.deletedAt, .datetime)
.field(FieldKeys.lastLogin, .datetime)
.unique(on: FieldKeys.username)
.unique(on: FieldKeys.email)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(UserModel.schema).delete()
}
}
}
extension UserModel {
struct Public: Content {
let id: UUID?
let username: String
let email: String
let role: Role
let name: String?
let lastname: String?
let address: String?
let zipCode: String?
let city: String?
let country: CountryCode?
let stripeID: String?
let createdAt: Date?
let updatedAt: Date?
let lastLogin: Date?
}
}
extension UserModel {
func convertToPublic() -> Public {
.init(
id: self.id,
username: self.username,
email: self.email,
role: self.role,
name: self.name,
lastname: self.lastname,
address: self.address,
zipCode: self.zipCode,
city: self.city,
country: self.Country,
stripeID: self.stripeID,
createdAt: self.createdAt,
updatedAt: self.updatedAt,
lastLogin: self.lastLogin
)
}
}
extension Collection where Element == UserModel {
func convertToPublic() -> [UserModel.Public] {
self.map { $0.convertToPublic() }
}
}