130 lines
6.3 KiB
Swift
130 lines
6.3 KiB
Swift
import Vapor
|
|
import PostgresKit
|
|
import Crypto
|
|
|
|
// MARK: Defaults for Administration
|
|
extension ManagedUser {
|
|
|
|
public static func all (on connection: any SQLDatabase) async throws -> [Self] {
|
|
return try await connection.raw("""
|
|
SELECT "id",
|
|
"email",
|
|
"full_name",
|
|
"active",
|
|
ARRAY (SELECT "role_name"
|
|
FROM "user_roles"
|
|
WHERE "user_roles"."user_id" = "users"."id") AS "roles"
|
|
FROM "users"
|
|
ORDER BY "email"
|
|
""")
|
|
.all (decoding: Self.self)
|
|
}
|
|
|
|
public static func fetch (_ id: UUID, on connection: any SQLDatabase) async throws -> Self? {
|
|
return try await connection.raw("""
|
|
SELECT "id",
|
|
"email",
|
|
"full_name",
|
|
"active",
|
|
"password",
|
|
ARRAY (SELECT "role_name"
|
|
FROM "user_roles"
|
|
WHERE "user_roles"."user_id" = "users"."id") AS "roles"
|
|
FROM "users"
|
|
WHERE "id" = \(bind: id)
|
|
""")
|
|
.first (decoding: Self.self)
|
|
}
|
|
|
|
public static func create (email: String, fullname: String, roles: [String], token: String, on connection: any SQLDatabase) async throws {
|
|
if roles.isEmpty {
|
|
try await connection.raw("""
|
|
WITH created AS (
|
|
INSERT INTO "users" (
|
|
"email",
|
|
"full_name",
|
|
"active")
|
|
VALUES (\(bind: email),
|
|
\(bind: fullname),
|
|
TRUE)
|
|
RETURNING "id"
|
|
)
|
|
INSERT INTO "user_tokens" ("user_id", "token")
|
|
SELECT "id", \(bind: token)
|
|
FROM created
|
|
""")
|
|
.run()
|
|
} else {
|
|
try await connection.raw("""
|
|
WITH "created" AS (
|
|
INSERT INTO "users" (
|
|
"email",
|
|
"full_name",
|
|
"active")
|
|
VALUES (\(bind: email),
|
|
\(bind: fullname),
|
|
TRUE)
|
|
RETURNING "id"
|
|
),
|
|
"roles" AS (
|
|
INSERT INTO "user_roles" ("user_id", "role_name")
|
|
SELECT "id", "role_name"
|
|
FROM "created"
|
|
CROSS JOIN unnest (\(bind: roles)) AS "role_name"
|
|
)
|
|
INSERT INTO "user_tokens" ("user_id", "token")
|
|
SELECT "id", \(bind: token)
|
|
FROM "created"
|
|
""")
|
|
.run()
|
|
}
|
|
}
|
|
|
|
public static func save (id: UUID, email: String, fullname: String, roles: [String], isActive: Bool, on connection: any SQLDatabase) async throws {
|
|
try await connection.raw ("""
|
|
WITH "update_user" AS (
|
|
UPDATE "users"
|
|
SET "email" = \(bind: email),
|
|
"full_name" = \(bind: fullname),
|
|
"active" = \(bind: isActive)
|
|
WHERE "id" = \(bind: id)
|
|
),
|
|
"desired_roles" AS (
|
|
SELECT "role_name"
|
|
FROM unnest (\(bind: roles)) "role_name"
|
|
),
|
|
"current_roles" AS (
|
|
SELECT "role_name"
|
|
FROM "user_roles"
|
|
WHERE "user_id" = \(bind: id)
|
|
),
|
|
"deleting_roles" AS (
|
|
DELETE FROM "user_roles"
|
|
WHERE "user_id" = \(bind: id)
|
|
AND NOT EXISTS (SELECT *
|
|
FROM "desired_roles"
|
|
WHERE "user_roles"."role_name" = "desired_roles"."role_name")
|
|
)
|
|
INSERT INTO "user_roles" ("user_id", "role_name")
|
|
SELECT \(bind: id), "name"
|
|
FROM "roles"
|
|
WHERE EXISTS (SELECT *
|
|
FROM "desired_roles"
|
|
WHERE "role_name" = "name")
|
|
AND NOT EXISTS (SELECT *
|
|
FROM "user_roles"
|
|
WHERE "user_id" = \(bind: id)
|
|
AND "role_name" = "name")
|
|
""")
|
|
.run()
|
|
}
|
|
|
|
public static func store (token: String, userId: UUID, on connection: any SQLDatabase) async throws {
|
|
try await connection.raw("""
|
|
INSERT INTO "user_tokens" ("user_id", "token")
|
|
VALUES (\(bind: userId), \(bind: token))
|
|
""")
|
|
.run()
|
|
}
|
|
}
|