User
final class User : Model
extension User: Reportable
extension User: ModelAuthenticatable
extension User: ModelSessionAuthenticatable
All accounts are of class User
.
The terms “account” and “sub-account” used throughout this documentatiion are all instances of User. The terms “primary account”, “parent account” and “master account” are used interchangeably to refer to any account that is not a sub-account.
A primary account holds the access level, verification token and recovery key, and all sub-accounts (if any) inherit these three credentials.
.id
and .parentID
are provisioned automatically, by the model protocols and
UsersController
account creation handlers respectively. .createdAt
, .updatedAt
and
.deletedAt
are all maintained automatically by the model protocols and should never be
otherwise modified.
-
Declaration
Swift
static let schema: String
-
The user’s ID, provisioned automatically.
Declaration
Swift
@ID var id: UUID?
-
The user’s publicly viewable username.
Declaration
Swift
@Field var username: String
-
An optional name for display alongside the username. “Display Name (@username)”
Declaration
Swift
@OptionalField var displayName: String?
-
An optional real world name for the user.
Declaration
Swift
@OptionalField var realName: String?
-
Concatenation of displayName + (@username) + realName, to speed search by name.
Declaration
Swift
@Field var userSearch: String
-
The user’s password, encrypted to BCrypt hash value.
Declaration
Swift
@Field var password: String
-
The user’s recovery key, encrypted to BCrypt hash value.
Declaration
Swift
@Field var recoveryKey: String
-
The registration code (or other identifier) used to activate the user for full read-write access. Prefixed with “*” after being used for password recovery.
Declaration
Swift
@OptionalField var verification: String?
-
The user’s
UserAccessLevel
, set to.unverified
at time of creation, or to the parent’s access level if a sub-account.Declaration
Swift
@Enum var accessLevel: UserAccessLevel
-
Only refers to the user’s ability to change their profile. Think of the profile fields as content, and mods can quarantine or lock that content, separate from outright banning a user.
Declaration
Swift
@Enum var moderationStatus: ContentModerationStatus
-
Number of successive failed attempts at password recovery.
Declaration
Swift
@Field var recoveryAttempts: Int
-
Cumulative number of reports submitted on user’s posts.
Declaration
Swift
@Field var reports: Int
-
If non-nil, the account has been handed a time out by a moderator. The account will have an effective access level of ‘Quarantined’ until the given time. Quarantine generally means normal Read access but user canot post or modify any text or image content. The user’s
accessLevel
field should not be changed when applying a temp quarantine. This way if mods later decide to ban the user, the end of the temp quarantine won’t reset the user’s access level (most likely to.verified
).Declaration
Swift
@Field var tempQuarantineUntil: Date?
-
The filename of the image for the user’s profile picture.
Declaration
Swift
@Field var userImage: String?
-
An optional bio or blurb or whatever.
Declaration
Swift
@OptionalField var about: String?
-
An optional home city, country, planet…
Declaration
Swift
@OptionalField var homeLocation: String?
-
An optional message to anybody viewing the profile. “I like turtles.”
Declaration
Swift
@OptionalField var message: String?
-
An optional preferred pronoun or form of address.
Declaration
Swift
@OptionalField var preferredPronoun: String?
-
An optional cabin number.
Declaration
Swift
@OptionalField var roomNumber: String?
-
An optional dinner team.
Declaration
Swift
@OptionalField var dinnerTeam: DinnerTeam?
-
Users that this user has muted. Muting removes twarrts, forums, forumPosts, and LFGs authored by muted users from API results. Here as an array instead of a to-many child relation because the primary operation is to use the list of all muted user IDs as a query filter, and we should never use the inverse relation (“muted by
”) for any purpose. Declaration
Swift
@Field var mutedUserIDs: [UUID]
-
Users that this user has blocked. Blocks act as a bidirectional mute between all accounts held by this user and all accounts held by the target user. However, this only records the blocks requested by this user, and only parent accounts can have this field filled in. Although a block applies to all related accounts of the target, here we only specify the specific account the user requested to block. Although we do need to access the ‘blocked by’ relation here, we build another structure for that, one that tracks all the accounts blocked by incoming or outgoing block requests.
Declaration
Swift
@Field var blockedUserIDs: [UUID]
-
If the user is a Moderator and is handling user reports, this will be set to the actionGroup of the reports. In this case, all the reports in the group are reporting on the same piece of content, and all have the same actionGroup. Any moderator actions the mod takes while handling reports get set tot his UUID. When the reports are closed, this gets set to nil.
Declaration
Swift
@Field var actionGroup: UUID?
-
Timestamp of the model’s creation, set automatically.
Declaration
Swift
@Timestamp var createdAt: Date?
-
Timestamp of the model’s last update, set automatically.
Declaration
Swift
@Timestamp var updatedAt: Date?
-
Timestamp of the model’s soft-deletion, set automatically.
Declaration
Swift
@Timestamp var deletedAt: Date?
-
Timestamp of the UserProfile’s last update.
Declaration
Swift
@Field var profileUpdatedAt: Date
-
If a sub-account, the ID of the User to which this user is associated, provisioned by
UsersController
handlers during creation.Declaration
Swift
@OptionalParent var parent: User?
-
The login token associated with this user, if they’re logged in. If logged in from multiple devices, all devices share the login token.
Declaration
Swift
@OptionalChild var token: Token?
-
For Shadow Event Organizers who create Performer profiles for their shadow event.
Declaration
Swift
@OptionalChild var performer: Performer?
-
The
ForumReaders
pivots contain read counts for each forum thread this user had viewed..Declaration
Swift
@Siblings var readForums: [Forum]
-
The child
FriendlyFez
objects created by this user.Declaration
Swift
@Children var owned_fezzes: [FriendlyFez]
-
The sibling
FriendlyFez
objects this user has joined.Declaration
Swift
@Siblings var joined_fezzes: [FriendlyFez]
-
The child
ProfileEdit
accountability records of this user.Declaration
Swift
@Children var edits: [ProfileEdit]
-
The sibling
KaraokeSongs
s this user has favorited.Declaration
Swift
@Siblings var favoriteSongs: [KaraokeSong]
-
Pivots for users this user has favorited. Technically
\UserFavorite.$favorites
could be used as well but we shouldn’t need to be looking at who has favorited a particular user.Declaration
Swift
@Children var favorites: [UserFavorite]
-
Declaration
Swift
init()
-
init(username:
password: recoveryKey: verification: parent: accessLevel: recoveryAttempts: reports: profileUpdatedAt: ) Initializes a new User.
Declaration
Swift
init( username: String, password: String, recoveryKey: String, verification: String? = nil, parent: User? = nil, accessLevel: UserAccessLevel, recoveryAttempts: Int = 0, reports: Int = 0, profileUpdatedAt: Date = Date(timeIntervalSince1970: 0) )
Parameters
username
The user’s username, unadorned (e.g. “grundoon”, not “@grundoon”).
password
A
BCrypt
hash of the user’s password. Please never store actual passwords.recoveryKey
A
BCrypt
hash of the user’s recovery key. Please never store the actual key.verification
A token of known identity, such as a provided code or a verified email address.
nil
if not yet verified.parent
If a sub-account, the
id
of the master acount, otherwisenil
.accessLevel
The user’s access level (see
UserAccessLevel
).recoveryAttempts
The number of successive failed attempts at password recovery, initially 0.
reports
The total number of reports made on the user’s posts, initially 0.
profileUpdatedAt
The timestamp of the associated profile’s last update, initially epoch.
-
allAccountIDs(on:
Asynchronous) Returns a list of IDs of all accounts associated with the
User
. If user is a primary account (has no.parentID
) it returns itself plus any sub-accounts. If user is a sub-account, it determines its parent, then returns the parent and all sub-accounts.Declaration
Swift
func allAccountIDs(on db: Database) async throws -> [UUID]
Parameters
req
The incoming request
Container
, which provides theEventLoop
on which the query must be run.Return Value
[UUID]
containing all the user’s associated IDs. -
allAccounts(on:
Asynchronous) Returns an array of
User
whose first element is the primary account and the remaining elements are sub-accounts of the primary account.Declaration
Swift
func allAccounts(on db: Database) async throws -> [User]
Parameters
db
The incoming request
Container
, which provides theEventLoop
on which the query must be run.Return Value
[User]
-
parentAccount(on:
Asynchronous) Returns the parent
User
of the user sending the request. If the requesting user has no parent, the user itself is returned.Declaration
Swift
func parentAccount(on req: Request) async throws -> User
Parameters
req
The incoming request
Container
, which provides reference to the sending user. -
Returns the ID of the parent account of the receiver. If the receiver has no parent, the receiver’s ID is returned.
Declaration
Swift
func parentAccountID() throws -> UUID
-
Declaration
Swift
func buildUserSearchString()
-
Ensures that either the receiver can edit/delete other users’ content (that is, they’re a moderator), or that they authored the content they’re trying to modify/delete themselves, and still have rights to edit their own content (that is, they aren’t banned/quarantined).
Declaration
Swift
func guardCanCreateContent(customErrorString: String = "user cannot modify this content") throws
-
Ensures that either the receiver can edit/delete other users’ content (that is, they’re a moderator), or that they authored the content they’re trying to modify/delete themselves, and still have rights to edit their own content (that is, they aren’t banned/quarantined).
Declaration
Swift
func guardCanModifyContent<T: Reportable>( _ content: T, customErrorString: String = "user cannot modify this content" ) throws
-
The receiver is the user performing the edit.
ofUser
may be nil if the reciever is editing their own profile. If it’s a moderator editing another user’s profile, remember that the receiver is the moderator, and the user whose profile is being edited is the ofUser parameter.This fn is very similar to
guardCanModifyContent()
; it’s a separate function because profile editing is likely to have different access requirements. In particular we’re likely to let unverified users edit their profile.Declaration
Swift
func guardCanEditProfile(ofUser profileOwner: User? = nil, customErrorString: String = "User cannot edit profile") throws
-
The report type for
User
reports.Declaration
Swift
var reportType: ReportType { get }
-
Declaration
Swift
var authorUUID: UUID { get }
-
Declaration
Swift
var autoQuarantineThreshold: Int { get }
-
Required username key for HTTP Basic Authorization.
Declaration
Swift
static let usernameKey: <<error type>>
-
Required password key for HTTP Basic Authorization.
Declaration
Swift
static let passwordHashKey: <<error type>>
-
Declaration
Swift
func verify(password: String) throws -> Bool