I read through the feedback and updated the naming convention and the schema. Here is the new updated one.
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.
DisplayName (Text 100)
Bio (Text)
Personal Website (Text 255)
Github (Text 100)
Twitter (Text 100)
Email (Text 255) UNQIUE
GravatarHash (Text)
Location (Text 100)
IsFromStackExchange (Boolean default FALSE)
StackExchangeId (Bigint)
IsSameAsInstance (Boolean default TRUE)
StackExchangeValidated (Date)
StackExchangeLastImported (Date)
IsEmailVerified (Boolean default FALSE)
IsGlobalSuspended (Boolean default FALSE)
GlobalSuspensionEndDate (DATE)
Communities
Table for each of the individual sites inside of a Codidact installation
Name (Text 40) UNQIUE
Tagline (Text 100) UNQIUE
URL (Text 255) UNQIUE
HelpText (Text)
FAQ (Text)
IsBeta (Boolean default FALSE)
TrustLevel
This needs to be specific to a site for when we get different language sites and it needs to be localized.
CommunitiesId (bigserial)
Name (Tex t 100) UNQIUE
Explanation (Text) UNQIUE
UsersCommunities
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.
CommunitiesId (bigserial)
DisplayName (Text 100)
Bio (Text)
Personal Website (Text 255)
Github (Text 100)
Twitter (Text 100)
Email (Text 255) UNQIUE
GravatarHash (Text)
Location (Text 100)
IsFromStackExchange (Boolean default FALSE)
StackExchangeId (Bigint)
IsSameAsInstance (Boolean default TRUE)
StackExchangeValidated (Date)
StackExchangeLastImported (Date)
SuspensionEndDate (Date)
IsSuspended (Boolean default FALSE)
TrustLevelId (bigserial)
CanAsk (Boolean default TRUE)
CanAnswer (Boolean default TRUE)
CanComment (Boolean default FALSE)
CanSuggestEdits (Boolean default FALSE)
CanFlag (Boolean default FALSE)
CanUpvote (Boolean default FALSE)
CanDownvote (Boolean default FALSE)
CanCloseVote (Boolean default FALSE)
CanEdit (Boolean default FALSE)
CanReview (Boolean default FALSE)
CanProtectPosts (Boolean default FALSE)
CanLockPosts (Boolean default FALSE)
CanSoftDeletePosts (Boolean default FALSE)
IsModerator (Boolean default FALSE)
IsDeleted (Boolean Default FALSE)
UNIQUE CONSTRAINT (UsersId,CommunitiesId)
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 UsersCommunities table.
CommunitiesId (bigserial)
UsersId (bigserial) UNQIUE
QuestionBanStartDate (date)
AnswerBanStartDate (date)
CommentBanStartDate (date)
SuggestedEditBanStartDate (date)
FlagBanStartDate (date)
UpvoteBanStartDate (date)
DownvoteBanStartDate (date)
EditBanStartDate (date)
ReviewBanStartDate (date)
ProtectBanStartDate (date)
LockPostsBanStartDate (date)
SoftDeleteBanStartDate (date)
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.
UsersId (bigserial)
CommunitiesId (bigserial)
Title (Text 255 Default NULL)
Body (Text)
Upvotes (bigint)
Downvotes (bigint)
NetVotes (bigint)
Score (decimal)
IsAccepted (Boolean Default FALSE)
IsQuestion (Boolean default TRUE)
IsAnswer (Boolean default FALSE)
IsBlog (Boolean default FALSE)
IsCanonical (Boolean default FALSE)
IsClosed (Boolean default FALSE)
IsProtected (Boolean default FALSE)
ParentId (bigserial Default NULL)
IsMeta (Boolean Default FALSE)
IsDeleted (Boolean Default FALSE)
UNIQUE CONSTRAINT (CommunitiesId,Title)
Comments
Table for the comments on posts, both questions and answers.
UsersId (bigserial)
PostsId (bigserial)
ParentCommentId (bigserial DEFAULT NULL)
Body (Text)
Upvotes (bigint DEFAULT 0)
Downvotes (bigint) DEFAULT 0)
NetVotes (bigint) DEFAULT 0
Score (decimal DEFAULT 0)
IsDeleted (Boolean Default FALSE)
DeletedAt (Date)
CommentsVotes
CommentsId (bigserial)
UsersId (bigserial)
VoteTypesId (bigserial)
UNIQUE CONSTRAINT (CommentsId,UsersId)
Tags
Table for all of the tags
CommunitiesId (bigserial)
Name (Text 100 NOT NULL)
Description (Text)
TagWiki (Text default NULL)
IsActive (Boolean default TRUE)
TagsSynonymId (bigserial FK to Tags default NULL)
Usages (bigint)
PostsTags
PostsId (bigserial)
TagsId (bigserial)
UNIQUE CONSTRAINT (PostsId,TagsId)
VoteTypes
Table for the vote types, upvote/downvote.
Name (Text)
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)