<commit_before>//
//  Vendor.swift
//  subber-api
//
//  Created by <NAME> on 9/27/16.
//
//

import Vapor
import Fluent
import Auth
import Turnstile
import BCrypt
import Foundation
import Stripe
import Sanitized

extension Node {

    func autoextract<T: Model>(type: T.Type, key: String) throws -> Node? {

        if var object = try? self.extract(key) as T {
            try object.save()
            return object.id
        }

        guard let object_id: String = try self.extract("\(key)_id") else {
            throw Abort.custom(status: .badRequest, message: "Missing value for \(key) or \(key)_id")
        }
        
        return .string(object_id)
    }
}

enum ApplicationState: String, NodeConvertible {
    
    case none = "none"
    case recieved = "recieved"
    case rejected = "rejected"
    case accepted = "accepted"
    
    init(node: Node, in context: Context) throws {
        
        guard let state = node.string.flatMap ({ ApplicationState(rawValue: $0) }) else {
            throw Abort.custom(status: .badRequest, message: "Invalid value for application state.")
        }
        
        self = state
    }
    
    func makeNode(context: Context = EmptyNode) throws -> Node {
        return .string(rawValue)
    }
}

extension BCryptSalt: NodeInitializable {
    
    public init(node: Node, in context: Context) throws {
        guard let salt = try node.string.flatMap ({ try BCryptSalt(string: $0) }) else {
            throw Abort.custom(status: .badRequest, message: "Invalid salt.")
        }
        
        self = salt
    }
}

final class Vendor: Model, Preparation, JSONConvertible, Sanitizable {
    
    static var permitted: [String] = ["contactName", "businessName", "parentCompanyName", "contactPhone", "contactEmail", "supportEmail", "publicWebsite", "dateCreated", "established", "category_id", "estimatedTotalSubscribers", "applicationState", "username", "password", "verification<PASSWORD>", "stripeAccountId", "cut"]
    
    var id: Node?
    var exists = false

    let contactName: String
    let contactPhone: String
    let contactEmail: String
    var applicationState: ApplicationState = .none
    var verificationState: LegalEntityVerificationStatus?
    
    let publicWebsite: String
    let supportEmail: String
    let businessName: String
    
    let parentCompanyName: String
    let established: String
    
    var category_id: Node?
    let estimatedTotalSubscribers: Int
    
    let dateCreated: Date

    var username: String
    var password: String
    var salt: BCryptSalt

    var stripeAccountId: String?
    
    let cut: Double?
    
    var missingFields: Bool
    var needsIdentityUpload: Bool
    
    var keys: Keys?
    
    init(node: Node, in context: Context) throws {
        
        id = try? node.extract("id")
        
        applicationState = try node.extract("applicationState")
        
        username = try node.extract("username")
        let password = try node.extract("password") as String
        
        if let salt = try? node.extract("salt") as String {
            self.salt = try BCryptSalt(string: salt)
            self.password = password
        } else {
            self.salt = BCryptSalt()
            self.password = <PASSWORD>(password: password, salt: salt)
        }
        
        contactName = try node.extract("contactName")
        businessName = try node.extract("businessName")
        parentCompanyName = try node.extract("parentCompanyName")
        
        contactPhone = try node.extract("contactPhone")
        contactEmail = try node.extract("contactEmail")
        supportEmail = try node.extract("supportEmail")
        publicWebsite = try node.extract("publicWebsite")
        
        established = try node.extract("established")
        dateCreated = (try? node.extract("dateCreated")) ?? Date()
        
        estimatedTotalSubscribers = try node.extract("estimatedTotalSubscribers")
        
        category_id = try node.autoextract(type: Category.self, key: "category")
        
        cut = (try? node.extract("cut")) ?? 0.08
        stripeAccountId = try? node.extract("stripeAccountId")
        verificationState = try? node.extract("verificationState")
        
        missingFields = try node.extract("missingFields")
        needsIdentityUpload = try node.extract("needsIdentityUpload")
        
        if stripeAccountId != nil {
            let publishable: String = try node.extract("publishableKey")
            let secret: String = try node.extract("secretKey")
            
            keys = try Keys(node: Node(node: ["secret" : secret, "publishable" : publishable]))
        }<commit_msg>Fix vendor creation endpoint.<commit_after>//
//  Vendor.swift
//  subber-api
//
//  Created by <NAME> on 9/27/16.
//
//

import Vapor
import Fluent
import Auth
import Turnstile
import BCrypt
import Foundation
import Stripe
import Sanitized

extension Node {

    func autoextract<T: Model>(type: T.Type, key: String) throws -> Node? {

        if var object = try? self.extract(key) as T {
            try object.save()
            return object.id
        }

        guard let object_id: String = try self.extract("\(key)_id") else {
            throw Abort.custom(status: .badRequest, message: "Missing value for \(key) or \(key)_id")
        }
        
        return .string(object_id)
    }
}

enum ApplicationState: String, NodeConvertible {
    
    case none = "none"
    case recieved = "recieved"
    case rejected = "rejected"
    case accepted = "accepted"
    
    init(node: Node, in context: Context) throws {
        
        guard let state = node.string.flatMap ({ ApplicationState(rawValue: $0) }) else {
            throw Abort.custom(status: .badRequest, message: "Invalid value for application state.")
        }
        
        self = state
    }
    
    func makeNode(context: Context = EmptyNode) throws -> Node {
        return .string(rawValue)
    }
}

extension BCryptSalt: NodeInitializable {
    
    public init(node: Node, in context: Context) throws {
        guard let salt = try node.string.flatMap ({ try BCryptSalt(string: $0) }) else {
            throw Abort.custom(status: .badRequest, message: "Invalid salt.")
        }
        
        self = salt
    }
}

final class Vendor: Model, Preparation, JSONConvertible, Sanitizable {
    
    static var permitted: [String] = ["contactName", "businessName", "parentCompanyName", "contactPhone", "contactEmail", "supportEmail", "publicWebsite", "dateCreated", "established", "category_id", "estimatedTotalSubscribers", "applicationState", "username", "password", "verification<PASSWORD>", "stripeAccountId", "cut"]
    
    var id: Node?
    var exists = false

    let contactName: String
    let contactPhone: String
    let contactEmail: String
    var applicationState: ApplicationState = .none
    var verificationState: LegalEntityVerificationStatus?
    
    let publicWebsite: String
    let supportEmail: String
    let businessName: String
    
    let parentCompanyName: String
    let established: String
    
    var category_id: Node?
    let estimatedTotalSubscribers: Int
    
    let dateCreated: Date

    var username: String
    var password: String
    var salt: BCryptSalt

    var stripeAccountId: String?
    
    let cut: Double?
    
    var missingFields: Bool
    var needsIdentityUpload: Bool
    
    var keys: Keys?
    
    init(node: Node, in context: Context) throws {
        
        id = try? node.extract("id")
        
        applicationState = try node.extract("applicationState")
        
        username = try node.extract("username")
        let password = try node.extract("password") as String
        
        if let salt = try? node.extract("salt") as String {
            self.salt = try BCryptSalt(string: salt)
            self.password = password
        } else {
            self.salt = BCryptSalt()
            self.password = BCrypt.hash(password: password, salt: salt)
        }
        
        contactName = try node.extract("contactName")
        businessName = try node.extract("businessName")
        parentCompanyName = try node.extract("parentCompanyName")
        
        contactPhone = try node.extract("contactPhone")
        contactEmail = try node.extract("contactEmail")
        supportEmail = try node.extract("supportEmail")
        publicWebsite = try node.extract("publicWebsite")
        
        established = try node.extract("established")
        dateCreated = (try? node.extract("dateCreated")) ?? Date()
        
        estimatedTotalSubscribers = try node.extract("estimatedTotalSubscribers")
        
        category_id = try node.autoextract(type: Category.self, key: "category")
        
        cut = (try? node.extract("cut")) ?? 0.08
        stripeAccountId = try? node.extract("stripeAccountId")
        verificationState = try? node.extract("verificationState")
        
        missingFields = try (node.extract("missingFields") ?? false)
        needsIdentityUpload = try (node.extract("needsIdentityUpload") ?? false)
        
        if stripeAccountId != nil {
            let publishable: String = try node.extract("publishableKey")
            let secret: String = try node.extract("secretKey")
            
            keys = try Keys(node: Node(node: ["secret" : secret, "publishable" : publishable]))
        }
{'fraction_non_alphanumeric': 0.10291448702893136, 'fraction_numerical': 0.002135155332550443, 'mean_word_length': 2.4747774480712166, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1054693', 'n_tokens_mistral': 2585, 'n_tokens_neox': 2509, 'n_words': 711}