This is where I got to on the schema, please read my convention post first.
Users
This table will hold the global user records for an Codidact Instance. A user should only have one email to login with, that would be stored here. I am leaving the password storage and hashing to the experts.
Email (Text 255) UNIQUE
IsEmailVerified (Boolean default FALSE)
IsGlobalSuspended (Boolean default FALSE)
GlobalSuspensionEndDate (DATE)
Sites
Each of the individual sites inside of a Codidact installation
Name (Text) UNIQUE
Tagline (Text) UNIQUE
URL (Text) UNIQUE
TrustLevel
Name for each trust level and an explanation of each that a user should get when they get to that level.
Name (Text) UNIQUE
Explanation (Text) UNIQUE
UsersSites
A user may want to join one site and not another, and having a join table between users and sites allows a user to be suspended or gain/lose privileges on a single site. I listed the privilege booleans in the order of lowest to highest, the privileges after IsModerator arenāt listed because we probably are going to take any of moderatorās lower privileges away without demodding them.
SitesId (bigserial)
DisplayName (Text)
Bio (Text)
PersonalWebsite (Text)
Github (Text)
Twitter (Text)
SuspensionEndDate (Date)
IsSuspended (Boolean default FALSE)
TrustLevelId (bigserial)
IsAbleToAsk (Boolean default TRUE)
IsAbleToAnswer (Boolean default TRUE)
IsAbleToComment (Boolean default FALSE)
IsAbleToSuggestEdits (Boolean default FALSE)
IsAbleToFlag (Boolean default FALSE)
IsAbleToUpvote (Boolean default FALSE)
IsAbleToDownvote (Boolean default FALSE)
IsAbleToCloseVote (Boolean default FALSE)
IsAbleToEdit (Boolean default FALSE)
IsAbleToReview (Boolean default FALSE)
IsAbleToProtectPosts (Boolean default FALSE)
IsAbleToLockPosts (Boolean default FALSE)
IsAbleToSoftDeletePosts (Boolean default FALSE)
IsModerator (Boolean default FALSE)
IsDeleted (Boolean Default FALSE)
UNIQUE CONSTRAINT (UsersId,SitesId)
UsersSuspensions
This table is for recording the specific privilege suspensions. The idea is that we will have an scheduled task running nightly that once the suspension is over will set the correct flag on the UsersSites table.
UsersId (bigserial) UNIQUE
QuestionBanEndDate (date)
AnswerBanEndDate (date)
CommentBanEndDate (date)
SuggestedEditBanEndDate (date)
FlagBanEndDate (date)
UpvoteBanEndDate (date)
DownvoteBanEndDate (date)
EditBanEndDate (date)
ReviewBanEndDate (date)
ProtectBanEndDate (date)
LockPostsBanEndDate (date)
SoftDeleteBanEndDate (date)
Posts
I thought about splitting into a Answers table and and QuestionsTable but doing it in the same table lets comments have a PostsId instead of a QuestionsId and a AnswersId. Meta posts are denoted by the IsMeta column. Still unsure on community wiki/FAQ posts.
SitesId (bigserial)
Title (Text Default NULL)
Body (Text)
Upvotes (smallint)
Downvote (smallint)
Score (smallint)
IsAccepted (Boolean Default FALSE)
ParentId (bigserial Default NULL)
IsMeta (Boolean Default FALSE)
IsDeleted (Boolean Default FALSE)
UNIQUE CONSTRAINT (SitesId,Title)
Comments
Table for the comments on posts, both questions and answers.
PostsId (bigserial)
ParentCommentId (bigserial DEFAULT NULL)
Body (Text)
Upvotes (smallint DEFAULT 0)
Downvote (smallint DEFAULT 0)
Score (smallint DEFAULT 0)
IsDeleted (Boolean Default FALSE)
CommentsVotes
CommentsId (bigserial)
UsersId (bigserial)
VoteTypesId (bigserial)
UNIQUE CONSTRAINT (CommentsId,UsersId)
Tags
SitesId (bigserial)
Name (Text NOT NULL)
Description (Text)
Usages (smallint)
UNIQUE CONSTRAINT (SitesId ,Name)
PostsTags
PostsId (bigserial)
TagsId (bigserial)
UNIQUE CONSTRAINT (PostsId,TagsId)
VoteTypes
Table for the vote types, upvote/downvote.
Name (Text) UNIQUE
PostVotes
The reason for this table is so that votes by spammers/serial voters can be undone.
PostsId (bigserial)
VoteTypesId (bigserial)
UsersId (bigserial)
UNIQUE CONSTRAINT (PostsId,UsersId)