updated sample

This commit is contained in:
Tony Tam 2014-02-19 16:46:11 -08:00
parent 641aada8a8
commit e92d4e6258
13 changed files with 226 additions and 214 deletions

View File

@ -1,8 +1,13 @@
import AssemblyKeys._ // put this at the top of the file import AssemblyKeys._ // put this at the top of the file
import com.github.siasia.PluginKeys._
import NativePackagerKeys._
packageArchetype.java_server
assemblySettings assemblySettings
scalariformSettings
organization := "com.wordnik" organization := "com.wordnik"
seq(webSettings :_*) seq(webSettings :_*)
@ -13,25 +18,22 @@ name := "scalatra-sample"
version := "0.1.0-SNAPSHOT" version := "0.1.0-SNAPSHOT"
scalaVersion := "2.9.2" scalaVersion := "2.10.0"
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "1.6.1" % "test", "org.scalatest" %% "scalatest" % "2.0" % "test",
"org.scalatra" % "scalatra" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra" % "2.3.0.M1",
"org.scalatra" % "scalatra-auth" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra-scalate" % "2.3.0.M1",
"org.scalatra" % "scalatra-scalate" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra-json" % "2.3.0.M1",
"org.scalatra" % "scalatra-json" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra-swagger" % "2.3.0.M1",
"org.scalatra" % "scalatra-fileupload" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra-swagger-ext" % "2.3.0.M1",
"org.scalatra" % "scalatra-swagger" % "2.2.1-SNAPSHOT", "org.scalatra" %% "scalatra-slf4j" % "2.3.0.M1",
"org.scalatra" % "scalatra-swagger-ext" % "2.2.1-SNAPSHOT",
"org.scalatra" % "scalatra-slf4j" % "2.2.1-SNAPSHOT",
"org.scalatra" % "scalatra-specs2" % "2.2.1-SNAPSHOT" % "test",
"org.json4s" %% "json4s-jackson" % "3.1.0", "org.json4s" %% "json4s-jackson" % "3.1.0",
"org.json4s" %% "json4s-ext" % "3.1.0", "org.json4s" %% "json4s-ext" % "3.1.0",
"commons-codec" % "commons-codec" % "1.7", "commons-codec" % "commons-codec" % "1.7",
"net.databinder.dispatch" %% "dispatch-core" % "0.9.5", "net.databinder.dispatch" %% "dispatch-core" % "0.9.5",
"net.databinder.dispatch" %% "json4s-jackson" % "0.9.5", "net.databinder.dispatch" %% "json4s-jackson" % "0.9.5",
"com.typesafe.akka" % "akka-actor" % "2.0.2", "com.typesafe.akka" %% "akka-actor" % "2.1.0",
"org.eclipse.jetty" % "jetty-server" % "8.1.7.v20120910" % "container;provided", "org.eclipse.jetty" % "jetty-server" % "8.1.7.v20120910" % "container;provided",
"org.eclipse.jetty" % "jetty-webapp" % "8.1.7.v20120910" % "container;provided", "org.eclipse.jetty" % "jetty-webapp" % "8.1.7.v20120910" % "container;provided",
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;compile;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar")) "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;compile;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar"))
@ -55,4 +57,3 @@ mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
case x => old(x) case x => old(x)
} }
} }

View File

@ -1 +1 @@
sbt.version=0.12.0 sbt.version=0.13.0

View File

@ -1,9 +1,7 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.4") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.10.1")
libraryDependencies <+= sbtVersion(v => v match { addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.6.4")
case "0.11.0" => "com.github.siasia" %% "xsbt-web-plugin" % "0.11.0-0.2.8"
case "0.11.1" => "com.github.siasia" %% "xsbt-web-plugin" % "0.11.1-0.2.10" addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.6.0")
case "0.11.2" => "com.github.siasia" %% "xsbt-web-plugin" % "0.11.2-0.2.11"
case "0.11.3" => "com.github.siasia" %% "xsbt-web-plugin" % "0.11.3-0.2.11.1" addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
case x if (x.startsWith("0.12")) => "com.github.siasia" %% "xsbt-web-plugin" % "0.12.0-0.2.11.1"
})

View File

@ -1,5 +1,6 @@
import apis._ import apis._
import com.wordnik.swagger.app.{ResourcesApp, SwaggerApp} import akka.actor.ActorSystem
import com.wordnik.swagger.app.{ ResourcesApp, SwaggerApp }
import javax.servlet.ServletContext import javax.servlet.ServletContext
import org.scalatra.LifeCycle import org.scalatra.LifeCycle
@ -7,10 +8,11 @@ class ScalatraBootstrap extends LifeCycle {
implicit val swagger = new SwaggerApp implicit val swagger = new SwaggerApp
override def init(context: ServletContext) { override def init(context: ServletContext) {
implicit val system = ActorSystem("mySystem")
try { try {
context mount (new UserApi, "/user/*")
context mount (new PetApi, "/pet/*") context mount (new PetApi, "/pet/*")
context mount (new StoreApi, "/store/*") context mount (new StoreApi, "/store/*")
context mount (new UserApi, "/user/*")
context mount (new ResourcesApp, "/api-docs/*") context mount (new ResourcesApp, "/api-docs/*")
} catch { } catch {
case e: Throwable => e.printStackTrace() case e: Throwable => e.printStackTrace()

View File

@ -1,11 +1,14 @@
package com.wordnik.swagger.app package com.wordnik.swagger.app
import com.wordnik.swagger.core.SwaggerSpec import _root_.akka.actor.ActorSystem
import org.scalatra.swagger.{JacksonSwaggerBase, Swagger}
import org.scalatra.ScalatraServlet
import org.json4s.{DefaultFormats, Formats}
class ResourcesApp(implicit val swagger: Swagger) extends ScalatraServlet with JacksonSwaggerBase { import org.scalatra.swagger.{ ApiInfo, SwaggerWithAuth, Swagger }
import org.scalatra.swagger.{ JacksonSwaggerBase, Swagger }
import org.scalatra.ScalatraServlet
import org.json4s.{ DefaultFormats, Formats }
class ResourcesApp(implicit protected val system: ActorSystem, val swagger: SwaggerApp)
extends ScalatraServlet with JacksonSwaggerBase {
before() { before() {
response.headers += ("Access-Control-Allow-Origin" -> "*") response.headers += ("Access-Control-Allow-Origin" -> "*")
} }
@ -14,7 +17,7 @@ class ResourcesApp(implicit val swagger: Swagger) extends ScalatraServlet with J
val port = request.getServerPort val port = request.getServerPort
val h = request.getServerName val h = request.getServerName
val prot = if (port == 443) "https" else "http" val prot = if (port == 443) "https" else "http"
val (proto, host) = if (port != 80 && port != 443) ("http", h+":"+port.toString) else (prot, h) val (proto, host) = if (port != 80 && port != 443) ("http", h + ":" + port.toString) else (prot, h)
"%s://%s%s%s".format( "%s://%s%s%s".format(
proto, proto,
host, host,
@ -23,5 +26,14 @@ class ResourcesApp(implicit val swagger: Swagger) extends ScalatraServlet with J
} }
} }
class SwaggerApp extends Swagger(SwaggerSpec.version, "1") class SwaggerApp extends Swagger(apiInfo = ApiSwagger.apiInfo, apiVersion = "1.0", swaggerVersion = "1.2")
object ApiSwagger {
val apiInfo = ApiInfo(
"Swagger Sample",
"A sample swagger server",
"http://developers.helloreverb.com",
"hello@helloreverb.com",
"All rights reserved",
"http://apache.org/licenses/LICENSE-2.0.html")
}

View File

@ -1,8 +1,7 @@
package apis package apis
import java.io.File
import com.wordnik.client.model.Pet import com.wordnik.client.model.Pet
import com.wordnik.swagger.core.ApiPropertiesReader
import org.scalatra.{ TypedParamSupport, ScalatraServlet } import org.scalatra.{ TypedParamSupport, ScalatraServlet }
import org.scalatra.swagger._ import org.scalatra.swagger._
import org.json4s._ import org.json4s._
@ -11,7 +10,7 @@ import org.scalatra.json.{ JValueResult, JacksonJsonSupport }
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
class PetApi (implicit val swagger: Swagger) extends ScalatraServlet class PetApi(implicit val swagger: Swagger) extends ScalatraServlet
with JacksonJsonSupport with JacksonJsonSupport
with SwaggerSupport { with SwaggerSupport {
protected implicit val jsonFormats: Formats = DefaultFormats protected implicit val jsonFormats: Formats = DefaultFormats
@ -24,73 +23,111 @@ class PetApi (implicit val swagger: Swagger) extends ScalatraServlet
response.headers += ("Access-Control-Allow-Origin" -> "*") response.headers += ("Access-Control-Allow-Origin" -> "*")
} }
val getPetByIdOperation = (apiOperation[Pet]("getPetById") val getPetByIdOperation = (apiOperation[Pet]("getPetById")
summary "Find pet by ID" summary "Find pet by ID"
parameters( parameters (
pathParam[Long]("petId").description(""))
)
get("/:petId", operation(getPetByIdOperation)) {
val petId = params.getOrElse("petId", halt(400))
println("petId: " + petId)
}
val deletePetOperation = (apiOperation[Unit]("deletePet")
summary "Deletes a pet"
parameters (
pathParam[String]("petId").description("")) pathParam[String]("petId").description(""))
) )
delete("/:petId", operation(deletePetOperation)) {
get("/:petId",operation(getPetByIdOperation)) {
val petId = params.getOrElse("petId", halt(400)) val petId = params.getOrElse("petId", halt(400))
println(petId) println("petId: " + petId)
} }
val partialUpdateOperation = (apiOperation[List[Pet]]("partialUpdate")
summary "partial updates to a pet"
parameters (
pathParam[String]("petId").description(""), bodyParam[Pet]("body").description(""))
)
patch("/:petId", operation(partialUpdateOperation)) {
val petId = params.getOrElse("petId", halt(400))
println("petId: " + petId)
val body = parsedBody.extract[Pet]
println("body: " + body)
}
val updatePetWithFormOperation = (apiOperation[Unit]("updatePetWithForm")
summary "Updates a pet in the store with form data"
parameters (
pathParam[String]("petId").description(""), queryParam[String]("name").description(""), queryParam[String]("status").description(""))
)
post("/:petId", operation(updatePetWithFormOperation)) {
val petId = params.getOrElse("petId", halt(400))
println("petId: " + petId)
val name = params.getAs[String]("name")
println("name: " + name)
val status = params.getAs[String]("status")
println("status: " + status)
}
val uploadFileOperation = (apiOperation[Unit]("uploadFile")
summary "uploads an image"
parameters (
queryParam[String]("additionalMetadata").description(""), bodyParam[File]("body").description("").optional)
)
post("/uploadImage", operation(uploadFileOperation)) {
val additionalMetadata = params.getAs[String]("additionalMetadata")
println("additionalMetadata: " + additionalMetadata)
val body = parsedBody.extract[File]
println("body: " + body)
}
val addPetOperation = (apiOperation[Unit]("addPet") val addPetOperation = (apiOperation[Unit]("addPet")
summary "Add a new pet to the store" summary "Add a new pet to the store"
parameters( parameters (
bodyParam[Pet]("body").description("")) bodyParam[Pet]("body").description(""))
) )
post("/", operation(addPetOperation)) {
post("/",operation(addPetOperation)) {
val body = parsedBody.extract[Pet] val body = parsedBody.extract[Pet]
println(body) println("body: " + body)
} }
val updatePetOperation = (apiOperation[Unit]("updatePet") val updatePetOperation = (apiOperation[Unit]("updatePet")
summary "Update an existing pet" summary "Update an existing pet"
parameters( parameters (
bodyParam[Pet]("body").description("")) bodyParam[Pet]("body").description(""))
) )
put("/", operation(updatePetOperation)) {
put("/",operation(updatePetOperation)) {
val body = parsedBody.extract[Pet] val body = parsedBody.extract[Pet]
println(body) println("body: " + body)
} }
val findPetsByStatusOperation = (apiOperation[List[Pet]]("findPetsByStatus") val findPetsByStatusOperation = (apiOperation[List[Pet]]("findPetsByStatus")
summary "Finds Pets by status" summary "Finds Pets by status"
parameters( parameters (
queryParam[String]("status").description("").defaultValue("available")) queryParam[String]("status").description("").defaultValue("available"))
) )
get("/findByStatus", operation(findPetsByStatusOperation)) {
get("/findByStatus",operation(findPetsByStatusOperation)) {
val status = params.getAs[String]("status") val status = params.getAs[String]("status")
println(status) println("status: " + status)
} }
val findPetsByTagsOperation = (apiOperation[List[Pet]]("findPetsByTags") val findPetsByTagsOperation = (apiOperation[List[Pet]]("findPetsByTags")
summary "Finds Pets by tags" summary "Finds Pets by tags"
parameters( parameters (
queryParam[String]("tags").description("")) queryParam[String]("tags").description(""))
) )
get("/findByTags", operation(findPetsByTagsOperation)) {
get("/findByTags",operation(findPetsByTagsOperation)) {
val tags = params.getAs[String]("tags") val tags = params.getAs[String]("tags")
println(tags) println("tags: " + tags)
} }
} }

View File

@ -1,8 +1,6 @@
package apis package apis
import com.wordnik.client.model.Order import com.wordnik.client.model.Order
import com.wordnik.swagger.core.ApiPropertiesReader
import org.scalatra.{ TypedParamSupport, ScalatraServlet } import org.scalatra.{ TypedParamSupport, ScalatraServlet }
import org.scalatra.swagger._ import org.scalatra.swagger._
import org.json4s._ import org.json4s._
@ -11,7 +9,7 @@ import org.scalatra.json.{ JValueResult, JacksonJsonSupport }
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
class StoreApi (implicit val swagger: Swagger) extends ScalatraServlet class StoreApi(implicit val swagger: Swagger) extends ScalatraServlet
with JacksonJsonSupport with JacksonJsonSupport
with SwaggerSupport { with SwaggerSupport {
protected implicit val jsonFormats: Formats = DefaultFormats protected implicit val jsonFormats: Formats = DefaultFormats
@ -24,45 +22,37 @@ class StoreApi (implicit val swagger: Swagger) extends ScalatraServlet
response.headers += ("Access-Control-Allow-Origin" -> "*") response.headers += ("Access-Control-Allow-Origin" -> "*")
} }
val getOrderByIdOperation = (apiOperation[Order]("getOrderById") val getOrderByIdOperation = (apiOperation[Order]("getOrderById")
summary "Find purchase order by ID" summary "Find purchase order by ID"
parameters( parameters (
pathParam[String]("orderId").description("")) pathParam[String]("orderId").description(""))
) )
get("/order/:orderId", operation(getOrderByIdOperation)) {
get("/order/:orderId",operation(getOrderByIdOperation)) {
val orderId = params.getOrElse("orderId", halt(400)) val orderId = params.getOrElse("orderId", halt(400))
println(orderId) println("orderId: " + orderId)
} }
val deleteOrderOperation = (apiOperation[Unit]("deleteOrder") val deleteOrderOperation = (apiOperation[Unit]("deleteOrder")
summary "Delete purchase order by ID" summary "Delete purchase order by ID"
parameters( parameters (
pathParam[String]("orderId").description("")) pathParam[String]("orderId").description(""))
) )
delete("/order/:orderId", operation(deleteOrderOperation)) {
delete("/order/:orderId",operation(deleteOrderOperation)) {
val orderId = params.getOrElse("orderId", halt(400)) val orderId = params.getOrElse("orderId", halt(400))
println(orderId) println("orderId: " + orderId)
} }
val placeOrderOperation = (apiOperation[Unit]("placeOrder") val placeOrderOperation = (apiOperation[Unit]("placeOrder")
summary "Place an order for a pet" summary "Place an order for a pet"
parameters( parameters (
bodyParam[Order]("body").description("")) bodyParam[Order]("body").description(""))
) )
post("/order", operation(placeOrderOperation)) {
post("/order",operation(placeOrderOperation)) {
val body = parsedBody.extract[Order] val body = parsedBody.extract[Order]
println(body) println("body: " + body)
} }
} }

View File

@ -1,8 +1,6 @@
package apis package apis
import com.wordnik.client.model.User import com.wordnik.client.model.User
import com.wordnik.swagger.core.ApiPropertiesReader
import org.scalatra.{ TypedParamSupport, ScalatraServlet } import org.scalatra.{ TypedParamSupport, ScalatraServlet }
import org.scalatra.swagger._ import org.scalatra.swagger._
import org.json4s._ import org.json4s._
@ -11,7 +9,7 @@ import org.scalatra.json.{ JValueResult, JacksonJsonSupport }
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
class UserApi (implicit val swagger: Swagger) extends ScalatraServlet class UserApi(implicit val swagger: Swagger) extends ScalatraServlet
with JacksonJsonSupport with JacksonJsonSupport
with SwaggerSupport { with SwaggerSupport {
protected implicit val jsonFormats: Formats = DefaultFormats protected implicit val jsonFormats: Formats = DefaultFormats
@ -24,117 +22,93 @@ class UserApi (implicit val swagger: Swagger) extends ScalatraServlet
response.headers += ("Access-Control-Allow-Origin" -> "*") response.headers += ("Access-Control-Allow-Origin" -> "*")
} }
val createUsersWithArrayInputOperation = (apiOperation[Unit]("createUsersWithArrayInput")
summary "Creates list of users with given input array"
parameters(
bodyParam[List[User]]("body").description(""))
)
post("/createWithArray",operation(createUsersWithArrayInputOperation)) {
val body = parsedBody.extract[List[User]]
println(body)
}
val createUserOperation = (apiOperation[Unit]("createUser") val createUserOperation = (apiOperation[Unit]("createUser")
summary "Create user" summary "Create user"
parameters( parameters (
bodyParam[User]("body").description("")) bodyParam[User]("body").description(""))
) )
post("/", operation(createUserOperation)) {
post("/",operation(createUserOperation)) {
val body = parsedBody.extract[User] val body = parsedBody.extract[User]
println(body) println("body: " + body)
} }
val createUsersWithArrayInputOperation = (apiOperation[Unit]("createUsersWithArrayInput")
summary "Creates list of users with given input array"
val createUsersWithListInputOperation = (apiOperation[Unit]("createUsersWithListInput") parameters (
summary "Creates list of users with given list input"
parameters(
bodyParam[List[User]]("body").description("")) bodyParam[List[User]]("body").description(""))
) )
post("/createWithArray", operation(createUsersWithArrayInputOperation)) {
post("/createWithList",operation(createUsersWithListInputOperation)) {
val body = parsedBody.extract[List[User]] val body = parsedBody.extract[List[User]]
println(body) println("body: " + body)
} }
val createUsersWithListInputOperation = (apiOperation[Unit]("createUsersWithListInput")
summary "Creates list of users with given list input"
parameters (
bodyParam[List[User]]("body").description(""))
)
post("/createWithList", operation(createUsersWithListInputOperation)) {
val body = parsedBody.extract[List[User]]
println("body: " + body)
}
val updateUserOperation = (apiOperation[Unit]("updateUser") val updateUserOperation = (apiOperation[Unit]("updateUser")
summary "Updated user" summary "Updated user"
parameters( parameters (
pathParam[String]("username").description(""),bodyParam[User]("body").description("")) pathParam[String]("username").description(""), bodyParam[User]("body").description(""))
) )
put("/:username", operation(updateUserOperation)) {
put("/:username",operation(updateUserOperation)) {
val username = params.getOrElse("username", halt(400)) val username = params.getOrElse("username", halt(400))
println(username) println("username: " + username)
val body = parsedBody.extract[User] val body = parsedBody.extract[User]
println(body) println("body: " + body)
} }
val deleteUserOperation = (apiOperation[Unit]("deleteUser") val deleteUserOperation = (apiOperation[Unit]("deleteUser")
summary "Delete user" summary "Delete user"
parameters( parameters (
pathParam[String]("username").description("")) pathParam[String]("username").description(""))
) )
delete("/:username", operation(deleteUserOperation)) {
delete("/:username",operation(deleteUserOperation)) {
val username = params.getOrElse("username", halt(400)) val username = params.getOrElse("username", halt(400))
println(username) println("username: " + username)
} }
val getUserByNameOperation = (apiOperation[User]("getUserByName") val getUserByNameOperation = (apiOperation[User]("getUserByName")
summary "Get user by user name" summary "Get user by user name"
parameters( parameters (
pathParam[String]("username").description("")) pathParam[String]("username").description(""))
) )
get("/:username", operation(getUserByNameOperation)) {
get("/:username",operation(getUserByNameOperation)) {
val username = params.getOrElse("username", halt(400)) val username = params.getOrElse("username", halt(400))
println(username) println("username: " + username)
} }
val loginUserOperation = (apiOperation[String]("loginUser") val loginUserOperation = (apiOperation[String]("loginUser")
summary "Logs user into the system" summary "Logs user into the system"
parameters( parameters (
queryParam[String]("username").description(""),queryParam[String]("password").description("")) queryParam[String]("username").description(""), queryParam[String]("password").description(""))
) )
get("/login", operation(loginUserOperation)) {
get("/login",operation(loginUserOperation)) {
val username = params.getAs[String]("username") val username = params.getAs[String]("username")
println(username) println("username: " + username)
val password = params.getAs[String]("password") val password = params.getAs[String]("password")
println(password) println("password: " + password)
} }
val logoutUserOperation = (apiOperation[Unit]("logoutUser") val logoutUserOperation = (apiOperation[Unit]("logoutUser")
summary "Logs out current logged in user session" summary "Logs out current logged in user session"
parameters( parameters ()
)
) )
get("/logout", operation(logoutUserOperation)) {
get("/logout",operation(logoutUserOperation)) {
} }
} }

View File

@ -1,9 +1,7 @@
package com.wordnik.client.model package com.wordnik.client.model
case class Category ( case class Category(
id: Option[Long], id: Option[Long],
name: Option[String] name: Option[String])
)

View File

@ -1,16 +1,14 @@
package com.wordnik.client.model package com.wordnik.client.model
import java.util.Date import java.util.Date
case class Order ( case class Order(
id: Option[Long], id: Option[Long],
petId: Option[Long], petId: Option[Long],
status: Option[String],// Order Status
quantity: Option[Int], quantity: Option[Int],
shipDate: Option[Date] status: Option[String], // Order Status
) shipDate: Option[Date])

View File

@ -2,12 +2,17 @@ package com.wordnik.client.model
import com.wordnik.client.model.Category import com.wordnik.client.model.Category
import com.wordnik.client.model.Tag import com.wordnik.client.model.Tag
case class Pet ( case class Pet(
tags: Option[List[Tag]], id: Long, // unique identifier for the pet
id: Option[Long],
category: Option[Category], category: Option[Category],
status: Option[String],// pet status in the store
name: Option[String], name: String,
photoUrls: Option[List[String]]
) photoUrls: Option[List[String]],
tags: Option[List[Tag]],
status: Option[String] // pet status in the store
)

View File

@ -1,9 +1,7 @@
package com.wordnik.client.model package com.wordnik.client.model
case class Tag ( case class Tag(
id: Option[Long], id: Option[Long],
name: Option[String] name: Option[String])
)

View File

@ -1,21 +1,20 @@
package com.wordnik.client.model package com.wordnik.client.model
case class User ( case class User(
id: Option[Long], id: Option[Long],
lastName: Option[String],
phone: Option[String],
username: Option[String],
email: Option[String],
userStatus: Option[Int],// User Status
firstName: Option[String], firstName: Option[String],
password: Option[String] username: Option[String],
lastName: Option[String],
email: Option[String],
password: Option[String],
phone: Option[String],
userStatus: Option[Int] // User Status
) )