diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..702fb65a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,28 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true, + "node": false + }, + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "sourceType": "module" + }, + "rules": { + "no-const-assign": "warn", + "no-this-before-super": "warn", + "no-undef": "warn", + "no-unreachable": "warn", + "no-unused-vars": "warn", + "constructor-super": "warn", + "valid-typeof": "warn" + }, + "globals": { + "$": true, + "session": true, + "siteURL": true + } +} \ No newline at end of file diff --git a/README.md b/README.md index 2a0afc6e..b759320b 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,10 @@ go get -u gopkg.in/sourcemap.v1 go get -u github.com/robertkrimen/otto +go get -u github.com/lib/pq + +go get -u github.com/denisenkom/go-mssqldb + go generate @@ -127,6 +131,8 @@ install.exe gosora.exe ``` +I'm looking into minimising the number of go gets for the advanced build and to maybe remove the platform and database engine specific dependencies if possible for those who don't need them. + # How do I install plugins? @@ -176,16 +182,26 @@ More images in the /images/ folder. Beware though, some of them are *really* out * github.com/gorilla/websocket Needed for Gosora's Optional WebSockets Module. +* github.com/robertkrimen/otto Needed for the upcoming JS plugin type. + + * gopkg.in/sourcemap.v1 Dependency for Otto. + +* github.com/lib/pq For interfacing with PostgreSQL. You will be able to pick this instead of MariaDB soon. + +* ithub.com/denisenkom/go-mssqldb For interfacing with MSSQL. You will be able to pick this instead of MSSQL soon. + # Bundled Plugins There are several plugins which are bundled with the software by default. These cover various common tasks which aren't common enough to clutter the core with or which have competing implementation methods (E.g. plugin_markdown vs plugin_bbcode for post mark-up). -* Hello World / Skeleton - Example plugins for helping you learn how to develop plugins. +* Hey There / Skeleton / Hey There (JS Version) - Example plugins for helping you learn how to develop plugins. * BBCode - A plugin in early development for converting BBCode Tags into HTML. * Markdown - An extremely simple plugin for converting Markdown into HTML. +* Social Groups - A WIP plugin which lets users create their own little discussion areas which they can administrate / moderate on their own. + # Developers There are a few things you'll need to know before running the more developer oriented features like the tests or the benchmarks. diff --git a/database.go b/database.go index 3a6804ca..fb0be30e 100644 --- a/database.go +++ b/database.go @@ -11,6 +11,8 @@ var dbAdapter string // ErrNoRows is an alias of sql.ErrNoRows, just in case we end up with non-database/sql datastores var ErrNoRows = sql.ErrNoRows +var _initDatabase func() error + func initDatabase() (err error) { // Engine specific code err = _initDatabase() diff --git a/gen_mssql.go b/gen_mssql.go new file mode 100644 index 00000000..27e7199a --- /dev/null +++ b/gen_mssql.go @@ -0,0 +1,962 @@ +// +build mssql + +// This file was generated by Gosora's Query Generator. Please try to avoid modifying this file, as it might change at any time. +package main + +import "log" +import "database/sql" + +// nolint +var getUserStmt *sql.Stmt +var getReplyStmt *sql.Stmt +var getUserReplyStmt *sql.Stmt +var getPasswordStmt *sql.Stmt +var getSettingsStmt *sql.Stmt +var getSettingStmt *sql.Stmt +var getFullSettingStmt *sql.Stmt +var getFullSettingsStmt *sql.Stmt +var getGroupsStmt *sql.Stmt +var getForumsStmt *sql.Stmt +var getForumsPermissionsStmt *sql.Stmt +var getPluginsStmt *sql.Stmt +var getThemesStmt *sql.Stmt +var getWidgetsStmt *sql.Stmt +var isPluginActiveStmt *sql.Stmt +var getUsersStmt *sql.Stmt +var getUsersOffsetStmt *sql.Stmt +var getWordFiltersStmt *sql.Stmt +var isThemeDefaultStmt *sql.Stmt +var getModlogsStmt *sql.Stmt +var getModlogsOffsetStmt *sql.Stmt +var getReplyTIDStmt *sql.Stmt +var getTopicFIDStmt *sql.Stmt +var getUserReplyUIDStmt *sql.Stmt +var hasLikedTopicStmt *sql.Stmt +var hasLikedReplyStmt *sql.Stmt +var getUserNameStmt *sql.Stmt +var getEmailsByUserStmt *sql.Stmt +var getTopicBasicStmt *sql.Stmt +var getActivityEntryStmt *sql.Stmt +var forumEntryExistsStmt *sql.Stmt +var groupEntryExistsStmt *sql.Stmt +var getForumTopicsOffsetStmt *sql.Stmt +var getExpiredScheduledGroupsStmt *sql.Stmt +var getSyncStmt *sql.Stmt +var getAttachmentStmt *sql.Stmt +var getTopicRepliesOffsetStmt *sql.Stmt +var getTopicListStmt *sql.Stmt +var getTopicUserStmt *sql.Stmt +var getTopicByReplyStmt *sql.Stmt +var getTopicRepliesStmt *sql.Stmt +var getForumTopicsStmt *sql.Stmt +var getProfileRepliesStmt *sql.Stmt +var getWatchersStmt *sql.Stmt +var createTopicStmt *sql.Stmt +var createReportStmt *sql.Stmt +var createReplyStmt *sql.Stmt +var createActionReplyStmt *sql.Stmt +var createLikeStmt *sql.Stmt +var addActivityStmt *sql.Stmt +var notifyOneStmt *sql.Stmt +var addEmailStmt *sql.Stmt +var createProfileReplyStmt *sql.Stmt +var addSubscriptionStmt *sql.Stmt +var createForumStmt *sql.Stmt +var addForumPermsToForumStmt *sql.Stmt +var addPluginStmt *sql.Stmt +var addThemeStmt *sql.Stmt +var createGroupStmt *sql.Stmt +var addModlogEntryStmt *sql.Stmt +var addAdminlogEntryStmt *sql.Stmt +var addAttachmentStmt *sql.Stmt +var createWordFilterStmt *sql.Stmt +var addForumPermsToGroupStmt *sql.Stmt +var replaceScheduleGroupStmt *sql.Stmt +var addRepliesToTopicStmt *sql.Stmt +var removeRepliesFromTopicStmt *sql.Stmt +var addTopicsToForumStmt *sql.Stmt +var removeTopicsFromForumStmt *sql.Stmt +var updateForumCacheStmt *sql.Stmt +var addLikesToTopicStmt *sql.Stmt +var addLikesToReplyStmt *sql.Stmt +var editTopicStmt *sql.Stmt +var editReplyStmt *sql.Stmt +var stickTopicStmt *sql.Stmt +var unstickTopicStmt *sql.Stmt +var lockTopicStmt *sql.Stmt +var unlockTopicStmt *sql.Stmt +var updateLastIPStmt *sql.Stmt +var updateSessionStmt *sql.Stmt +var setPasswordStmt *sql.Stmt +var setAvatarStmt *sql.Stmt +var setUsernameStmt *sql.Stmt +var changeGroupStmt *sql.Stmt +var activateUserStmt *sql.Stmt +var updateUserLevelStmt *sql.Stmt +var incrementUserScoreStmt *sql.Stmt +var incrementUserPostsStmt *sql.Stmt +var incrementUserBigpostsStmt *sql.Stmt +var incrementUserMegapostsStmt *sql.Stmt +var incrementUserTopicsStmt *sql.Stmt +var editProfileReplyStmt *sql.Stmt +var updateForumStmt *sql.Stmt +var updateSettingStmt *sql.Stmt +var updatePluginStmt *sql.Stmt +var updatePluginInstallStmt *sql.Stmt +var updateThemeStmt *sql.Stmt +var updateUserStmt *sql.Stmt +var updateGroupPermsStmt *sql.Stmt +var updateGroupRankStmt *sql.Stmt +var updateGroupStmt *sql.Stmt +var updateEmailStmt *sql.Stmt +var verifyEmailStmt *sql.Stmt +var setTempGroupStmt *sql.Stmt +var updateWordFilterStmt *sql.Stmt +var bumpSyncStmt *sql.Stmt +var deleteReplyStmt *sql.Stmt +var deleteProfileReplyStmt *sql.Stmt +var deleteForumPermsByForumStmt *sql.Stmt +var deleteActivityStreamMatchStmt *sql.Stmt +var deleteWordFilterStmt *sql.Stmt +var reportExistsStmt *sql.Stmt +var groupCountStmt *sql.Stmt +var modlogCountStmt *sql.Stmt +var addForumPermsToForumAdminsStmt *sql.Stmt +var addForumPermsToForumStaffStmt *sql.Stmt +var addForumPermsToForumMembersStmt *sql.Stmt +var notifyWatchersStmt *sql.Stmt + +// nolint +func _gen_mssql() (err error) { + if dev.DebugMode { + log.Print("Building the generated statements") + } + + log.Print("Preparing getUser statement.") + getUserStmt, err = db.Prepare("SELECT [name],[group],[is_super_admin],[avatar],[message],[url_prefix],[url_name],[level] FROM [users] WHERE [uid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [name],[group],[is_super_admin],[avatar],[message],[url_prefix],[url_name],[level] FROM [users] WHERE [uid] = ?1") + return err + } + + log.Print("Preparing getReply statement.") + getReplyStmt, err = db.Prepare("SELECT [tid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress],[likeCount] FROM [replies] WHERE [rid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [tid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress],[likeCount] FROM [replies] WHERE [rid] = ?1") + return err + } + + log.Print("Preparing getUserReply statement.") + getUserReplyStmt, err = db.Prepare("SELECT [uid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress] FROM [users_replies] WHERE [rid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [uid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress] FROM [users_replies] WHERE [rid] = ?1") + return err + } + + log.Print("Preparing getPassword statement.") + getPasswordStmt, err = db.Prepare("SELECT [password],[salt] FROM [users] WHERE [uid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [password],[salt] FROM [users] WHERE [uid] = ?1") + return err + } + + log.Print("Preparing getSettings statement.") + getSettingsStmt, err = db.Prepare("SELECT [name],[content],[type] FROM [settings]") + if err != nil { + log.Print("Bad Query: ","SELECT [name],[content],[type] FROM [settings]") + return err + } + + log.Print("Preparing getSetting statement.") + getSettingStmt, err = db.Prepare("SELECT [content],[type] FROM [settings] WHERE [name] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [content],[type] FROM [settings] WHERE [name] = ?1") + return err + } + + log.Print("Preparing getFullSetting statement.") + getFullSettingStmt, err = db.Prepare("SELECT [name],[type],[constraints] FROM [settings] WHERE [name] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [name],[type],[constraints] FROM [settings] WHERE [name] = ?1") + return err + } + + log.Print("Preparing getFullSettings statement.") + getFullSettingsStmt, err = db.Prepare("SELECT [name],[content],[type],[constraints] FROM [settings]") + if err != nil { + log.Print("Bad Query: ","SELECT [name],[content],[type],[constraints] FROM [settings]") + return err + } + + log.Print("Preparing getGroups statement.") + getGroupsStmt, err = db.Prepare("SELECT [gid],[name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag] FROM [users_groups]") + if err != nil { + log.Print("Bad Query: ","SELECT [gid],[name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag] FROM [users_groups]") + return err + } + + log.Print("Preparing getForums statement.") + getForumsStmt, err = db.Prepare("SELECT [fid],[name],[desc],[active],[preset],[parentID],[parentType],[topicCount],[lastTopicID],[lastReplyerID] FROM [forums] ORDER BY fid ASC") + if err != nil { + log.Print("Bad Query: ","SELECT [fid],[name],[desc],[active],[preset],[parentID],[parentType],[topicCount],[lastTopicID],[lastReplyerID] FROM [forums] ORDER BY fid ASC") + return err + } + + log.Print("Preparing getForumsPermissions statement.") + getForumsPermissionsStmt, err = db.Prepare("SELECT [gid],[fid],[permissions] FROM [forums_permissions] ORDER BY gid ASC,fid ASC") + if err != nil { + log.Print("Bad Query: ","SELECT [gid],[fid],[permissions] FROM [forums_permissions] ORDER BY gid ASC,fid ASC") + return err + } + + log.Print("Preparing getPlugins statement.") + getPluginsStmt, err = db.Prepare("SELECT [uname],[active],[installed] FROM [plugins]") + if err != nil { + log.Print("Bad Query: ","SELECT [uname],[active],[installed] FROM [plugins]") + return err + } + + log.Print("Preparing getThemes statement.") + getThemesStmt, err = db.Prepare("SELECT [uname],[default] FROM [themes]") + if err != nil { + log.Print("Bad Query: ","SELECT [uname],[default] FROM [themes]") + return err + } + + log.Print("Preparing getWidgets statement.") + getWidgetsStmt, err = db.Prepare("SELECT [position],[side],[type],[active],[location],[data] FROM [widgets] ORDER BY position ASC") + if err != nil { + log.Print("Bad Query: ","SELECT [position],[side],[type],[active],[location],[data] FROM [widgets] ORDER BY position ASC") + return err + } + + log.Print("Preparing isPluginActive statement.") + isPluginActiveStmt, err = db.Prepare("SELECT [active] FROM [plugins] WHERE [uname] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [active] FROM [plugins] WHERE [uname] = ?1") + return err + } + + log.Print("Preparing getUsers statement.") + getUsersStmt, err = db.Prepare("SELECT [uid],[name],[group],[active],[is_super_admin],[avatar] FROM [users]") + if err != nil { + log.Print("Bad Query: ","SELECT [uid],[name],[group],[active],[is_super_admin],[avatar] FROM [users]") + return err + } + + log.Print("Preparing getUsersOffset statement.") + getUsersOffsetStmt, err = db.Prepare("SELECT [uid],[name],[group],[active],[is_super_admin],[avatar] FROM [users] OFFSET ?1 ROWS FETCH NEXT ?2 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [uid],[name],[group],[active],[is_super_admin],[avatar] FROM [users] OFFSET ?1 ROWS FETCH NEXT ?2 ROWS ONLY") + return err + } + + log.Print("Preparing getWordFilters statement.") + getWordFiltersStmt, err = db.Prepare("SELECT [wfid],[find],[replacement] FROM [word_filters]") + if err != nil { + log.Print("Bad Query: ","SELECT [wfid],[find],[replacement] FROM [word_filters]") + return err + } + + log.Print("Preparing isThemeDefault statement.") + isThemeDefaultStmt, err = db.Prepare("SELECT [default] FROM [themes] WHERE [uname] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [default] FROM [themes] WHERE [uname] = ?1") + return err + } + + log.Print("Preparing getModlogs statement.") + getModlogsStmt, err = db.Prepare("SELECT [action],[elementID],[elementType],[ipaddress],[actorID],[doneAt] FROM [moderation_logs]") + if err != nil { + log.Print("Bad Query: ","SELECT [action],[elementID],[elementType],[ipaddress],[actorID],[doneAt] FROM [moderation_logs]") + return err + } + + log.Print("Preparing getModlogsOffset statement.") + getModlogsOffsetStmt, err = db.Prepare("SELECT [action],[elementID],[elementType],[ipaddress],[actorID],[doneAt] FROM [moderation_logs] OFFSET ?1 ROWS FETCH NEXT ?2 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [action],[elementID],[elementType],[ipaddress],[actorID],[doneAt] FROM [moderation_logs] OFFSET ?1 ROWS FETCH NEXT ?2 ROWS ONLY") + return err + } + + log.Print("Preparing getReplyTID statement.") + getReplyTIDStmt, err = db.Prepare("SELECT [tid] FROM [replies] WHERE [rid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [tid] FROM [replies] WHERE [rid] = ?1") + return err + } + + log.Print("Preparing getTopicFID statement.") + getTopicFIDStmt, err = db.Prepare("SELECT [parentID] FROM [topics] WHERE [tid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [parentID] FROM [topics] WHERE [tid] = ?1") + return err + } + + log.Print("Preparing getUserReplyUID statement.") + getUserReplyUIDStmt, err = db.Prepare("SELECT [uid] FROM [users_replies] WHERE [rid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [uid] FROM [users_replies] WHERE [rid] = ?1") + return err + } + + log.Print("Preparing hasLikedTopic statement.") + hasLikedTopicStmt, err = db.Prepare("SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'topics'") + if err != nil { + log.Print("Bad Query: ","SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'topics'") + return err + } + + log.Print("Preparing hasLikedReply statement.") + hasLikedReplyStmt, err = db.Prepare("SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'replies'") + if err != nil { + log.Print("Bad Query: ","SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'replies'") + return err + } + + log.Print("Preparing getUserName statement.") + getUserNameStmt, err = db.Prepare("SELECT [name] FROM [users] WHERE [uid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [name] FROM [users] WHERE [uid] = ?1") + return err + } + + log.Print("Preparing getEmailsByUser statement.") + getEmailsByUserStmt, err = db.Prepare("SELECT [email],[validated],[token] FROM [emails] WHERE [uid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [email],[validated],[token] FROM [emails] WHERE [uid] = ?1") + return err + } + + log.Print("Preparing getTopicBasic statement.") + getTopicBasicStmt, err = db.Prepare("SELECT [title],[content] FROM [topics] WHERE [tid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [title],[content] FROM [topics] WHERE [tid] = ?1") + return err + } + + log.Print("Preparing getActivityEntry statement.") + getActivityEntryStmt, err = db.Prepare("SELECT [actor],[targetUser],[event],[elementType],[elementID] FROM [activity_stream] WHERE [asid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [actor],[targetUser],[event],[elementType],[elementID] FROM [activity_stream] WHERE [asid] = ?1") + return err + } + + log.Print("Preparing forumEntryExists statement.") + forumEntryExistsStmt, err = db.Prepare("SELECT [fid] FROM [forums] WHERE [name] = '' ORDER BY fid ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [fid] FROM [forums] WHERE [name] = '' ORDER BY fid ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY") + return err + } + + log.Print("Preparing groupEntryExists statement.") + groupEntryExistsStmt, err = db.Prepare("SELECT [gid] FROM [users_groups] WHERE [name] = '' ORDER BY gid ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [gid] FROM [users_groups] WHERE [name] = '' ORDER BY gid ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY") + return err + } + + log.Print("Preparing getForumTopicsOffset statement.") + getForumTopicsOffsetStmt, err = db.Prepare("SELECT [tid],[title],[content],[createdBy],[is_closed],[sticky],[createdAt],[lastReplyAt],[lastReplyBy],[parentID],[postCount],[likeCount] FROM [topics] WHERE [parentID] = ?1 ORDER BY sticky DESC,lastReplyAt DESC,createdBy DESC OFFSET ?2 ROWS FETCH NEXT ?3 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [tid],[title],[content],[createdBy],[is_closed],[sticky],[createdAt],[lastReplyAt],[lastReplyBy],[parentID],[postCount],[likeCount] FROM [topics] WHERE [parentID] = ?1 ORDER BY sticky DESC,lastReplyAt DESC,createdBy DESC OFFSET ?2 ROWS FETCH NEXT ?3 ROWS ONLY") + return err + } + + log.Print("Preparing getExpiredScheduledGroups statement.") + getExpiredScheduledGroupsStmt, err = db.Prepare("SELECT [uid] FROM [users_groups_scheduler] WHERE GETUTCDATE() > [revert_at] AND [temporary] = 1") + if err != nil { + log.Print("Bad Query: ","SELECT [uid] FROM [users_groups_scheduler] WHERE GETUTCDATE() > [revert_at] AND [temporary] = 1") + return err + } + + log.Print("Preparing getSync statement.") + getSyncStmt, err = db.Prepare("SELECT [last_update] FROM [sync]") + if err != nil { + log.Print("Bad Query: ","SELECT [last_update] FROM [sync]") + return err + } + + log.Print("Preparing getAttachment statement.") + getAttachmentStmt, err = db.Prepare("SELECT [sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path] FROM [attachments] WHERE [path] = ?1 AND [sectionID] = ?2 AND [sectionTable] = ?3") + if err != nil { + log.Print("Bad Query: ","SELECT [sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path] FROM [attachments] WHERE [path] = ?1 AND [sectionID] = ?2 AND [sectionTable] = ?3") + return err + } + + log.Print("Preparing getTopicRepliesOffset statement.") + getTopicRepliesOffsetStmt, err = db.Prepare("SELECT [replies].[rid],[replies].[content],[replies].[createdBy],[replies].[createdAt],[replies].[lastEdit],[replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level],[replies].[ipaddress],[replies].[likeCount],[replies].[actionType] FROM [replies] LEFT JOIN [users] ON [replies].[createdBy] = [users].[uid] WHERE [replies].[tid] = ?1 OFFSET ?2 ROWS FETCH NEXT ?3 ROWS ONLY") + if err != nil { + log.Print("Bad Query: ","SELECT [replies].[rid],[replies].[content],[replies].[createdBy],[replies].[createdAt],[replies].[lastEdit],[replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level],[replies].[ipaddress],[replies].[likeCount],[replies].[actionType] FROM [replies] LEFT JOIN [users] ON [replies].[createdBy] = [users].[uid] WHERE [replies].[tid] = ?1 OFFSET ?2 ROWS FETCH NEXT ?3 ROWS ONLY") + return err + } + + log.Print("Preparing getTopicList statement.") + getTopicListStmt, err = db.Prepare("SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[is_closed],[topics].[sticky],[topics].[createdAt],[topics].[parentID],[users].[name],[users].[avatar] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") + if err != nil { + log.Print("Bad Query: ","SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[is_closed],[topics].[sticky],[topics].[createdAt],[topics].[parentID],[users].[name],[users].[avatar] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") + return err + } + + log.Print("Preparing getTopicUser statement.") + getTopicUserStmt, err = db.Prepare("SELECT [topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[users].[name],[users].[avatar],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [tid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[users].[name],[users].[avatar],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [tid] = ?1") + return err + } + + log.Print("Preparing getTopicByReply statement.") + getTopicByReplyStmt, err = db.Prepare("SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[topics].[data] FROM [replies] LEFT JOIN [topics] ON [replies].[tid] = [topics].[tid] WHERE [rid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[topics].[data] FROM [replies] LEFT JOIN [topics] ON [replies].[tid] = [topics].[tid] WHERE [rid] = ?1") + return err + } + + log.Print("Preparing getTopicReplies statement.") + getTopicRepliesStmt, err = db.Prepare("SELECT [replies].[rid],[replies].[content],[replies].[createdBy],[replies].[createdAt],[replies].[lastEdit],[replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level],[replies].[ipaddress] FROM [replies] LEFT JOIN [users] ON [replies].[createdBy] = [users].[uid] WHERE [tid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [replies].[rid],[replies].[content],[replies].[createdBy],[replies].[createdAt],[replies].[lastEdit],[replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level],[replies].[ipaddress] FROM [replies] LEFT JOIN [users] ON [replies].[createdBy] = [users].[uid] WHERE [tid] = ?1") + return err + } + + log.Print("Preparing getForumTopics statement.") + getForumTopicsStmt, err = db.Prepare("SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[is_closed],[topics].[sticky],[topics].[createdAt],[topics].[lastReplyAt],[topics].[parentID],[users].[name],[users].[avatar] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [topics].[parentID] = ?1 ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") + if err != nil { + log.Print("Bad Query: ","SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[is_closed],[topics].[sticky],[topics].[createdAt],[topics].[lastReplyAt],[topics].[parentID],[users].[name],[users].[avatar] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [topics].[parentID] = ?1 ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") + return err + } + + log.Print("Preparing getProfileReplies statement.") + getProfileRepliesStmt, err = db.Prepare("SELECT [users_replies].[rid],[users_replies].[content],[users_replies].[createdBy],[users_replies].[createdAt],[users_replies].[lastEdit],[users_replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group] FROM [users_replies] LEFT JOIN [users] ON [users_replies].[createdBy] = [users].[uid] WHERE [users_replies].[uid] = ?1") + if err != nil { + log.Print("Bad Query: ","SELECT [users_replies].[rid],[users_replies].[content],[users_replies].[createdBy],[users_replies].[createdAt],[users_replies].[lastEdit],[users_replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group] FROM [users_replies] LEFT JOIN [users] ON [users_replies].[createdBy] = [users].[uid] WHERE [users_replies].[uid] = ?1") + return err + } + + log.Print("Preparing getWatchers statement.") + getWatchersStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing createTopic statement.") + createTopicStmt, err = db.Prepare("INSERT INTO [topics] ([parentID],[title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[ipaddress],[words],[createdBy]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [topics] ([parentID],[title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[ipaddress],[words],[createdBy]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,?)") + return err + } + + log.Print("Preparing createReport statement.") + createReportStmt, err = db.Prepare("INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[createdBy],[data],[parentID],[css_class]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,1,'report')") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[createdBy],[data],[parentID],[css_class]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,1,'report')") + return err + } + + log.Print("Preparing createReply statement.") + createReplyStmt, err = db.Prepare("INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[ipaddress],[words],[createdBy]) VALUES (?,?,?,GETUTCDATE(),?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[ipaddress],[words],[createdBy]) VALUES (?,?,?,GETUTCDATE(),?,?,?)") + return err + } + + log.Print("Preparing createActionReply statement.") + createActionReplyStmt, err = db.Prepare("INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy]) VALUES (?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy]) VALUES (?,?,?,?)") + return err + } + + log.Print("Preparing createLike statement.") + createLikeStmt, err = db.Prepare("INSERT INTO [likes] ([weight],[targetItem],[targetType],[sentBy]) VALUES (?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [likes] ([weight],[targetItem],[targetType],[sentBy]) VALUES (?,?,?,?)") + return err + } + + log.Print("Preparing addActivity statement.") + addActivityStmt, err = db.Prepare("INSERT INTO [activity_stream] ([actor],[targetUser],[event],[elementType],[elementID]) VALUES (?,?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [activity_stream] ([actor],[targetUser],[event],[elementType],[elementID]) VALUES (?,?,?,?,?)") + return err + } + + log.Print("Preparing notifyOne statement.") + notifyOneStmt, err = db.Prepare("INSERT INTO [activity_stream_matches] ([watcher],[asid]) VALUES (?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [activity_stream_matches] ([watcher],[asid]) VALUES (?,?)") + return err + } + + log.Print("Preparing addEmail statement.") + addEmailStmt, err = db.Prepare("INSERT INTO [emails] ([email],[uid],[validated],[token]) VALUES (?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [emails] ([email],[uid],[validated],[token]) VALUES (?,?,?,?)") + return err + } + + log.Print("Preparing createProfileReply statement.") + createProfileReplyStmt, err = db.Prepare("INSERT INTO [users_replies] ([uid],[content],[parsed_content],[createdAt],[createdBy],[ipaddress]) VALUES (?,?,?,GETUTCDATE(),?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [users_replies] ([uid],[content],[parsed_content],[createdAt],[createdBy],[ipaddress]) VALUES (?,?,?,GETUTCDATE(),?,?)") + return err + } + + log.Print("Preparing addSubscription statement.") + addSubscriptionStmt, err = db.Prepare("INSERT INTO [activity_subscriptions] ([user],[targetID],[targetType],[level]) VALUES (?,?,?,2)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [activity_subscriptions] ([user],[targetID],[targetType],[level]) VALUES (?,?,?,2)") + return err + } + + log.Print("Preparing createForum statement.") + createForumStmt, err = db.Prepare("INSERT INTO [forums] ([name],[desc],[active],[preset]) VALUES (?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [forums] ([name],[desc],[active],[preset]) VALUES (?,?,?,?)") + return err + } + + log.Print("Preparing addForumPermsToForum statement.") + addForumPermsToForumStmt, err = db.Prepare("INSERT INTO [forums_permissions] ([gid],[fid],[preset],[permissions]) VALUES (?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [forums_permissions] ([gid],[fid],[preset],[permissions]) VALUES (?,?,?,?)") + return err + } + + log.Print("Preparing addPlugin statement.") + addPluginStmt, err = db.Prepare("INSERT INTO [plugins] ([uname],[active],[installed]) VALUES (?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [plugins] ([uname],[active],[installed]) VALUES (?,?,?)") + return err + } + + log.Print("Preparing addTheme statement.") + addThemeStmt, err = db.Prepare("INSERT INTO [themes] ([uname],[default]) VALUES (?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [themes] ([uname],[default]) VALUES (?,?)") + return err + } + + log.Print("Preparing createGroup statement.") + createGroupStmt, err = db.Prepare("INSERT INTO [users_groups] ([name],[tag],[is_admin],[is_mod],[is_banned],[permissions]) VALUES (?,?,?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [users_groups] ([name],[tag],[is_admin],[is_mod],[is_banned],[permissions]) VALUES (?,?,?,?,?,?)") + return err + } + + log.Print("Preparing addModlogEntry statement.") + addModlogEntryStmt, err = db.Prepare("INSERT INTO [moderation_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [moderation_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())") + return err + } + + log.Print("Preparing addAdminlogEntry statement.") + addAdminlogEntryStmt, err = db.Prepare("INSERT INTO [administration_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [administration_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())") + return err + } + + log.Print("Preparing addAttachment statement.") + addAttachmentStmt, err = db.Prepare("INSERT INTO [attachments] ([sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path]) VALUES (?,?,?,?,?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [attachments] ([sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path]) VALUES (?,?,?,?,?,?)") + return err + } + + log.Print("Preparing createWordFilter statement.") + createWordFilterStmt, err = db.Prepare("INSERT INTO [word_filters] ([find],[replacement]) VALUES (?,?)") + if err != nil { + log.Print("Bad Query: ","INSERT INTO [word_filters] ([find],[replacement]) VALUES (?,?)") + return err + } + + log.Print("Preparing addForumPermsToGroup statement.") + addForumPermsToGroupStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing replaceScheduleGroup statement.") + replaceScheduleGroupStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addRepliesToTopic statement.") + addRepliesToTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing removeRepliesFromTopic statement.") + removeRepliesFromTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addTopicsToForum statement.") + addTopicsToForumStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing removeTopicsFromForum statement.") + removeTopicsFromForumStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateForumCache statement.") + updateForumCacheStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addLikesToTopic statement.") + addLikesToTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addLikesToReply statement.") + addLikesToReplyStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing editTopic statement.") + editTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing editReply statement.") + editReplyStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing stickTopic statement.") + stickTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing unstickTopic statement.") + unstickTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing lockTopic statement.") + lockTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing unlockTopic statement.") + unlockTopicStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateLastIP statement.") + updateLastIPStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateSession statement.") + updateSessionStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing setPassword statement.") + setPasswordStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing setAvatar statement.") + setAvatarStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing setUsername statement.") + setUsernameStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing changeGroup statement.") + changeGroupStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing activateUser statement.") + activateUserStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateUserLevel statement.") + updateUserLevelStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing incrementUserScore statement.") + incrementUserScoreStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing incrementUserPosts statement.") + incrementUserPostsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing incrementUserBigposts statement.") + incrementUserBigpostsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing incrementUserMegaposts statement.") + incrementUserMegapostsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing incrementUserTopics statement.") + incrementUserTopicsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing editProfileReply statement.") + editProfileReplyStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateForum statement.") + updateForumStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateSetting statement.") + updateSettingStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updatePlugin statement.") + updatePluginStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updatePluginInstall statement.") + updatePluginInstallStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateTheme statement.") + updateThemeStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateUser statement.") + updateUserStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateGroupPerms statement.") + updateGroupPermsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateGroupRank statement.") + updateGroupRankStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateGroup statement.") + updateGroupStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateEmail statement.") + updateEmailStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing verifyEmail statement.") + verifyEmailStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing setTempGroup statement.") + setTempGroupStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing updateWordFilter statement.") + updateWordFilterStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing bumpSync statement.") + bumpSyncStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing deleteReply statement.") + deleteReplyStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing deleteProfileReply statement.") + deleteProfileReplyStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing deleteForumPermsByForum statement.") + deleteForumPermsByForumStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing deleteActivityStreamMatch statement.") + deleteActivityStreamMatchStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing deleteWordFilter statement.") + deleteWordFilterStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing reportExists statement.") + reportExistsStmt, err = db.Prepare("SELECT COUNT(*) AS [count] FROM [topics] WHERE [data] = ? AND [data] != '' AND [parentID] = 1") + if err != nil { + log.Print("Bad Query: ","SELECT COUNT(*) AS [count] FROM [topics] WHERE [data] = ? AND [data] != '' AND [parentID] = 1") + return err + } + + log.Print("Preparing groupCount statement.") + groupCountStmt, err = db.Prepare("SELECT COUNT(*) AS [count] FROM [users_groups]") + if err != nil { + log.Print("Bad Query: ","SELECT COUNT(*) AS [count] FROM [users_groups]") + return err + } + + log.Print("Preparing modlogCount statement.") + modlogCountStmt, err = db.Prepare("SELECT COUNT(*) AS [count] FROM [moderation_logs]") + if err != nil { + log.Print("Bad Query: ","SELECT COUNT(*) AS [count] FROM [moderation_logs]") + return err + } + + log.Print("Preparing addForumPermsToForumAdmins statement.") + addForumPermsToForumAdminsStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addForumPermsToForumStaff statement.") + addForumPermsToForumStaffStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing addForumPermsToForumMembers statement.") + addForumPermsToForumMembersStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + log.Print("Preparing notifyWatchers statement.") + notifyWatchersStmt, err = db.Prepare("") + if err != nil { + log.Print("Bad Query: ","") + return err + } + + return nil +} diff --git a/gen_mysql.go b/gen_mysql.go index a286023d..e7c8a27f 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -1,4 +1,4 @@ -// +build !pgsql !sqlite !mssql +// +build !pgsql, !sqlite, !mssql /* This file was generated by Gosora's Query Generator. Please try to avoid modifying this file, as it might change at any time. */ @@ -350,7 +350,7 @@ func _gen_mysql() (err error) { } log.Print("Preparing getTopicRepliesOffset statement.") - getTopicRepliesOffsetStmt, err = db.Prepare("SELECT `replies`.`rid`,`replies`.`content`,`replies`.`createdBy`,`replies`.`createdAt`,`replies`.`lastEdit`,`replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level`,`replies`.`ipaddress`,`replies`.`likeCount`,`replies`.`actionType` FROM `replies` LEFT JOIN `users` ON `replies`.`createdBy` = `users`.`uid` WHERE `tid` = ? LIMIT ?,?") + getTopicRepliesOffsetStmt, err = db.Prepare("SELECT `replies`.`rid`,`replies`.`content`,`replies`.`createdBy`,`replies`.`createdAt`,`replies`.`lastEdit`,`replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level`,`replies`.`ipaddress`,`replies`.`likeCount`,`replies`.`actionType` FROM `replies` LEFT JOIN `users` ON `replies`.`createdBy` = `users`.`uid` WHERE `replies`.`tid` = ? LIMIT ?,?") if err != nil { return err } diff --git a/general_test.go b/general_test.go index 46a4ad92..4ade42d7 100644 --- a/general_test.go +++ b/general_test.go @@ -3,6 +3,7 @@ package main import ( //"os" "bytes" + "errors" "log" "strconv" "strings" @@ -12,24 +13,57 @@ import ( "net/http/httptest" "testing" "time" + + "./install/install" //"runtime/pprof" //_ "github.com/go-sql-driver/mysql" //"github.com/erikstmartin/go-testdb" //"github.com/husobee/vestigo" ) -var dbTest *sql.DB +//var dbTest *sql.DB var dbProd *sql.DB var gloinited bool -func gloinit() error { +func gloinit() (err error) { dev.DebugMode = false //nogrouplog = true - startTime = time.Now() - processConfig() - err := initThemes() + err = processConfig() + if err != nil { + return err + } + + err = initThemes() + if err != nil { + return err + } + + switchToTestDB() + + adap, ok := install.Lookup(dbAdapter) + if !ok { + return errors.New("We couldn't find the adapter '" + dbAdapter + "'") + } + adap.SetConfig(dbConfig.Host, dbConfig.Username, dbConfig.Password, dbConfig.Dbname, dbConfig.Port) + + err = adap.InitDatabase() + if err != nil { + return err + } + + err = adap.TableDefs() + if err != nil { + return err + } + + err = adap.CreateAdmin() + if err != nil { + return err + } + + err = adap.InitialData() if err != nil { return err } diff --git a/install-linux b/install-linux index c0e7b6c4..da75ec05 100644 --- a/install-linux +++ b/install-linux @@ -4,6 +4,9 @@ go get -u github.com/go-sql-driver/mysql echo "Installing the PostgreSQL Driver" go get -u github.com/lib/pq +echo "Installing the MSSQL Driver" +go get -u github.com/denisenkom/go-mssqldb + echo "Installing bcrypt" go get -u golang.org/x/crypto/bcrypt @@ -16,9 +19,10 @@ go get -u github.com/gorilla/websocket echo "Installing Sourcemap (dependency for OttoJS)" go get -u gopkg.in/sourcemap.v1 -echo "Install OttoJS" +echo "Installing OttoJS" go get -u github.com/robertkrimen/otto + echo "Building the installer" cd ./install go generate diff --git a/install.bat b/install.bat index 06f656af..592383bd 100644 --- a/install.bat +++ b/install.bat @@ -15,6 +15,13 @@ if %errorlevel% neq 0 ( exit /b %errorlevel% ) +echo Installing the MSSQL Driver +go get -u github.com/denisenkom/go-mssqldb +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + echo Installing the bcrypt library go get -u golang.org/x/crypto/bcrypt if %errorlevel% neq 0 ( @@ -64,6 +71,7 @@ if %errorlevel% neq 0 ( exit /b %errorlevel% ) + echo Building the installer go generate go build ./install diff --git a/install/install.go b/install/install.go index ee640de0..1355d806 100644 --- a/install/install.go +++ b/install/install.go @@ -8,27 +8,17 @@ package main import ( "bufio" - "database/sql" + "errors" "fmt" "os" "runtime/debug" "strconv" - "../query_gen/lib" + "./install" ) -const saltLength int = 32 - -var db *sql.DB var scanner *bufio.Scanner -var dbAdapter = "mysql" -var dbHost string -var dbUsername string -var dbPassword string -var dbName string -var dbPort string - var siteShortName string var siteName string var siteURL string @@ -43,13 +33,8 @@ var defaultSiteName = "Site Name" var defaultsiteURL = "localhost" var defaultServerPort = "80" // 8080's a good one, if you're testing and don't want it to clash with port 80 -// func() error, removing type to satisfy lint -var initDatabase = _initMysql -var tableDefs = _tableDefsMysql -var initialData = _initialDataMysql - func main() { - // Capture panics rather than immediately closing the window on Windows + // Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows defer func() { r := recover() if r != nil { @@ -63,15 +48,15 @@ func main() { scanner = bufio.NewScanner(os.Stdin) fmt.Println("Welcome to Gosora's Installer") fmt.Println("We're going to take you through a few steps to help you get started :)") - if !getDatabaseDetails() { + adap, ok := handleDatabaseDetails() + if !ok { err := scanner.Err() if err != nil { fmt.Println(err) } else { - fmt.Println("Something went wrong!") + err = errors.New("Something went wrong!") } - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } @@ -80,73 +65,36 @@ func main() { if err != nil { fmt.Println(err) } else { - fmt.Println("Something went wrong!") + err = errors.New("Something went wrong!") } - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } - err := initDatabase() + err := adap.InitDatabase() if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } - err = tableDefs() + err = adap.TableDefs() if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } - hashedPassword, salt, err := BcryptGeneratePassword("password") + err = adap.CreateAdmin() if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } - // Build the admin user query - adminUserStmt, err := qgen.Builder.SimpleInsert("users", "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip", "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'") + err = adap.InitialData() if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } - // Run the admin user query - _, err = adminUserStmt.Exec(hashedPassword, salt) - if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() - return - } - - err = initialData() - if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() - return - } - - if dbAdapter == "mysql" { - err = _mysqlSeedDatabase() - if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() - return - } - } - configContents := []byte(`package main func init() { @@ -164,11 +112,18 @@ func init() { site.Language = "english" // Database details - dbConfig.Host = "` + dbHost + `" - dbConfig.Username = "` + dbUsername + `" - dbConfig.Password = "` + dbPassword + `" - dbConfig.Dbname = "` + dbName + `" - dbConfig.Port = "` + dbPort + `" // You probably won't need to change this + dbConfig.Host = "` + adap.DbHost() + `" + dbConfig.Username = "` + adap.DbUsername() + `" + dbConfig.Password = "` + adap.DbPassword() + `" + dbConfig.Dbname = "` + adap.DbName() + `" + dbConfig.Port = "` + adap.DbPort() + `" // You probably won't need to change this + + // Test Database details + dbConfig.TestHost = "" + dbConfig.TestUsername = "" + dbConfig.TestPassword = "" + dbConfig.TestDbname = "" // The name of the test database, leave blank to disable. DON'T USE YOUR PRODUCTION DATABASE FOR THIS. LEAVE BLANK IF YOU DON'T KNOW WHAT THIS MEANS. + dbConfig.TestPort = "" // Limiters config.MaxRequestSize = 5 * megabyte @@ -202,24 +157,21 @@ func init() { //dev.SuperDebug = true //dev.TemplateDebug = true //dev.Profiling = true + //dev.TestDB = true } `) fmt.Println("Opening the configuration file") configFile, err := os.Create("./config.go") if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } fmt.Println("Writing to the configuration file...") _, err = configFile.Write(configContents) if err != nil { - fmt.Println(err) - fmt.Println("Aborting installation...") - pressAnyKey() + abortError(err) return } @@ -232,21 +184,39 @@ func init() { pressAnyKey() } -func getDatabaseDetails() bool { - fmt.Println("Which database driver do you wish to use? mysql, mysql, or mysql? Default: mysql") - if !scanner.Scan() { - return false +func abortError(err error) { + fmt.Println(err) + fmt.Println("Aborting installation...") + pressAnyKey() +} + +func handleDatabaseDetails() (adap install.InstallAdapter, ok bool) { + var dbHost string + var dbUsername string + var dbPassword string + var dbName string + var dbPort string + + for { + fmt.Println("Which database adapter do you wish to use? mysql, mysql, or mysql? Default: mysql") + if !scanner.Scan() { + return nil, false + } + dbAdapter := scanner.Text() + if dbAdapter == "" { + dbAdapter = defaultAdapter + } + adap, ok = install.Lookup(dbAdapter) + if ok { + break + } + fmt.Println("That adapter doesn't exist") } - dbAdapter = scanner.Text() - if dbAdapter == "" { - dbAdapter = defaultAdapter - } - dbAdapter = setDBAdapter(dbAdapter) fmt.Println("Set database adapter to " + dbAdapter) fmt.Println("Database Host? Default: " + defaultHost) if !scanner.Scan() { - return false + return nil, false } dbHost = scanner.Text() if dbHost == "" { @@ -256,7 +226,7 @@ func getDatabaseDetails() bool { fmt.Println("Database Username? Default: " + defaultUsername) if !scanner.Scan() { - return false + return nil, false } dbUsername = scanner.Text() if dbUsername == "" { @@ -266,7 +236,7 @@ func getDatabaseDetails() bool { fmt.Println("Database Password? Default: ''") if !scanner.Scan() { - return false + return nil, false } dbPassword = scanner.Text() if len(dbPassword) == 0 { @@ -278,14 +248,16 @@ func getDatabaseDetails() bool { fmt.Println("Database Name? Pick a name you like or one provided to you. Default: " + defaultDbname) if !scanner.Scan() { - return false + return nil, false } dbName = scanner.Text() if dbName == "" { dbName = defaultDbname } fmt.Println("Set database name to " + dbName) - return true + + adap.SetConfig(dbHost, dbUsername, dbPassword, dbName, adap.DefaultPort()) + return adap, true } func getSiteDetails() bool { @@ -338,16 +310,6 @@ func getSiteDetails() bool { return true } -func setDBAdapter(name string) string { - switch name { - //case "wip-pgsql": - // set_pgsql_adapter() - // return "wip-pgsql" - } - _setMysqlAdapter() - return "mysql" -} - func obfuscatePassword(password string) (out string) { for i := 0; i < len(password); i++ { out += "*" diff --git a/install/install/install.go b/install/install/install.go new file mode 100644 index 00000000..ea732ecf --- /dev/null +++ b/install/install/install.go @@ -0,0 +1,45 @@ +package install + +import ( + "../../query_gen/lib" +) + +var adapters = make(map[string]InstallAdapter) + +type InstallAdapter interface { + Name() string + DefaultPort() string + SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) + InitDatabase() error + TableDefs() error + InitialData() error + CreateAdmin() error + + DBHost() string + DBUsername() string + DBPassword() string + DBName() string + DBPort() string +} + +func Lookup(name string) (InstallAdapter, bool) { + adap, ok := adapters[name] + return adap, ok +} + +func createAdmin() error { + hashedPassword, salt, err := BcryptGeneratePassword("password") + if err != nil { + return err + } + + // Build the admin user query + adminUserStmt, err := qgen.Builder.SimpleInsert("users", "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip", "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'") + if err != nil { + return err + } + + // Run the admin user query + _, err = adminUserStmt.Exec(hashedPassword, salt) + return err +} diff --git a/install/install/mssql.go b/install/install/mssql.go new file mode 100644 index 00000000..58c95ed1 --- /dev/null +++ b/install/install/mssql.go @@ -0,0 +1,173 @@ +/* +* +* Gosora MSSQL Interface +* Under heavy development +* Copyright Azareal 2017 - 2018 +* + */ +package install + +import ( + "bytes" + "database/sql" + "fmt" + "io/ioutil" + "log" + "net/url" + "path/filepath" + "strconv" + "strings" + + "../../query_gen/lib" + _ "github.com/denisenkom/go-mssqldb" +) + +func init() { + adapters["mssql"] = &MssqlInstaller{dbHost: ""} +} + +type MssqlInstaller struct { + db *sql.DB + dbHost string + dbUsername string + dbPassword string + dbName string + dbInstance string + dbPort string +} + +func (ins *MssqlInstaller) SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) { + ins.dbHost = dbHost + ins.dbUsername = dbUsername + ins.dbPassword = dbPassword + ins.dbName = dbName + ins.dbInstance = "" // You can't set this from the installer right now, it allows you to connect to a named instance instead of a port + ins.dbPort = dbPort +} + +func (ins *MssqlInstaller) Name() string { + return "mssql" +} + +func (ins *MssqlInstaller) DefaultPort() string { + return "1433" +} + +func (ins *MssqlInstaller) InitDatabase() (err error) { + query := url.Values{} + query.Add("database", ins.dbName) + u := &url.URL{ + Scheme: "sqlserver", + User: url.UserPassword(ins.dbUsername, ins.dbPassword), + Host: ins.dbHost + ":" + ins.dbPort, + Path: ins.dbInstance, + RawQuery: query.Encode(), + } + log.Print("u.String() ", u.String()) + + db, err := sql.Open("mssql", u.String()) + if err != nil { + return err + } + + // Make sure that the connection is alive.. + err = db.Ping() + if err != nil { + return err + } + fmt.Println("Successfully connected to the database") + + // TODO: Create the database, if it doesn't exist + + // Ready the query builder + qgen.Builder.SetConn(db) + err = qgen.Builder.SetAdapter("mssql") + if err != nil { + return err + } + ins.db = db + + return nil +} + +func (ins *MssqlInstaller) TableDefs() (err error) { + //fmt.Println("Creating the tables") + files, _ := ioutil.ReadDir("./schema/mssql/") + for _, f := range files { + if !strings.HasPrefix(f.Name(), "query_") { + continue + } + + var table, ext string + table = strings.TrimPrefix(f.Name(), "query_") + ext = filepath.Ext(table) + if ext != ".sql" { + continue + } + table = strings.TrimSuffix(table, ext) + + fmt.Println("Creating table '" + table + "'") + data, err := ioutil.ReadFile("./schema/mssql/" + f.Name()) + if err != nil { + return err + } + data = bytes.TrimSpace(data) + + _, err = ins.db.Exec(string(data)) + if err != nil { + fmt.Println("Failed query:", string(data)) + return err + } + } + //fmt.Println("Finished creating the tables") + return nil +} + +func (ins *MssqlInstaller) InitialData() (err error) { + //fmt.Println("Seeding the tables") + data, err := ioutil.ReadFile("./schema/mssql/inserts.sql") + if err != nil { + return err + } + data = bytes.TrimSpace(data) + + statements := bytes.Split(data, []byte(";")) + for key, statement := range statements { + if len(statement) == 0 { + continue + } + + fmt.Println("Executing query #" + strconv.Itoa(key) + " " + string(statement)) + _, err = ins.db.Exec(string(statement)) + if err != nil { + return err + } + } + + //fmt.Println("Finished inserting the database data") + return nil +} + +func (ins *MssqlInstaller) CreateAdmin() error { + return createAdmin() +} + +func (ins *MssqlInstaller) DBHost() string { + return ins.dbHost +} + +func (ins *MssqlInstaller) DBUsername() string { + return ins.dbUsername +} + +func (ins *MssqlInstaller) DBPassword() string { + return ins.dbPassword +} + +func (ins *MssqlInstaller) DBName() string { + return ins.dbName +} + +func (ins *MssqlInstaller) DBPort() string { + return ins.dbPort +} diff --git a/install/mysql.go b/install/install/mysql.go similarity index 56% rename from install/mysql.go rename to install/install/mysql.go index 2ac9ca46..f34f3834 100644 --- a/install/mysql.go +++ b/install/install/mysql.go @@ -4,7 +4,7 @@ * Copyright Azareal 2017 - 2018 * */ -package main +package install import ( "bytes" @@ -15,25 +15,47 @@ import ( "strconv" "strings" - "../query_gen/lib" + "../../query_gen/lib" _ "github.com/go-sql-driver/mysql" ) //var dbCollation string = "utf8mb4_general_ci" -func _setMysqlAdapter() { - dbPort = "3306" - initDatabase = _initMysql - tableDefs = _tableDefsMysql - initialData = _initialDataMysql +func init() { + adapters["mysql"] = &MysqlInstaller{dbHost: ""} } -func _initMysql() (err error) { - _dbPassword := dbPassword +type MysqlInstaller struct { + db *sql.DB + dbHost string + dbUsername string + dbPassword string + dbName string + dbPort string +} + +func (ins *MysqlInstaller) SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) { + ins.dbHost = dbHost + ins.dbUsername = dbUsername + ins.dbPassword = dbPassword + ins.dbName = dbName + ins.dbPort = dbPort +} + +func (ins *MysqlInstaller) Name() string { + return "mysql" +} + +func (ins *MysqlInstaller) DefaultPort() string { + return "3306" +} + +func (ins *MysqlInstaller) InitDatabase() (err error) { + _dbPassword := ins.dbPassword if _dbPassword != "" { _dbPassword = ":" + _dbPassword } - db, err = sql.Open("mysql", dbUsername+_dbPassword+"@tcp("+dbHost+":"+dbPort+")/") + db, err := sql.Open("mysql", ins.dbUsername+_dbPassword+"@tcp("+ins.dbHost+":"+ins.dbPort+")/") if err != nil { return err } @@ -46,22 +68,22 @@ func _initMysql() (err error) { fmt.Println("Successfully connected to the database") var waste string - err = db.QueryRow("SHOW DATABASES LIKE '" + dbName + "'").Scan(&waste) + err = db.QueryRow("SHOW DATABASES LIKE '" + ins.dbName + "'").Scan(&waste) if err != nil && err != sql.ErrNoRows { return err } if err == sql.ErrNoRows { fmt.Println("Unable to find the database. Attempting to create it") - _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + dbName) + _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + ins.dbName) if err != nil { return err } fmt.Println("The database was successfully created") } - fmt.Println("Switching to database " + dbName) - _, err = db.Exec("USE " + dbName) + fmt.Println("Switching to database " + ins.dbName) + _, err = db.Exec("USE " + ins.dbName) if err != nil { return err } @@ -73,10 +95,11 @@ func _initMysql() (err error) { return err } + ins.db = db return nil } -func _tableDefsMysql() error { +func (ins *MysqlInstaller) TableDefs() error { //fmt.Println("Creating the tables") files, _ := ioutil.ReadDir("./schema/mysql/") for _, f := range files { @@ -99,7 +122,7 @@ func _tableDefsMysql() error { } data = bytes.TrimSpace(data) - _, err = db.Exec(string(data)) + _, err = ins.db.Exec(string(data)) if err != nil { fmt.Println("Failed query:", string(data)) return err @@ -113,47 +136,51 @@ func _tableDefsMysql() error { /* TODO: Implement the html-attribute setting type before deploying this */ /*INSERT INTO settings(`name`,`content`,`type`) VALUES ('meta_desc','','html-attribute');*/ -func _initialDataMysql() error { - return nil // Coming Soon - - /*fmt.Println("Seeding the tables") +func (ins *MysqlInstaller) InitialData() error { + //fmt.Println("Seeding the tables") data, err := ioutil.ReadFile("./schema/mysql/inserts.sql") if err != nil { return err } data = bytes.TrimSpace(data) - fmt.Println("Executing query",string(data)) - _, err = db.Exec(string(data)) - if err != nil { - return err - } - - //fmt.Println("Finished inserting the database data") - return nil*/ -} - -func _mysqlSeedDatabase() error { - fmt.Println("Opening the database seed file") - sqlContents, err := ioutil.ReadFile("./mysql.sql") - if err != nil { - return err - } - - fmt.Println("Preparing installation queries") - sqlContents = bytes.TrimSpace(sqlContents) - statements := bytes.Split(sqlContents, []byte(";")) + statements := bytes.Split(data, []byte(";")) for key, statement := range statements { if len(statement) == 0 { continue } fmt.Println("Executing query #" + strconv.Itoa(key) + " " + string(statement)) - _, err = db.Exec(string(statement)) + _, err = ins.db.Exec(string(statement)) if err != nil { return err } } - fmt.Println("Finished inserting the database data") + + //fmt.Println("Finished inserting the database data") return nil } + +func (ins *MysqlInstaller) CreateAdmin() error { + return createAdmin() +} + +func (ins *MysqlInstaller) DBHost() string { + return ins.dbHost +} + +func (ins *MysqlInstaller) DBUsername() string { + return ins.dbUsername +} + +func (ins *MysqlInstaller) DBPassword() string { + return ins.dbPassword +} + +func (ins *MysqlInstaller) DBName() string { + return ins.dbName +} + +func (ins *MysqlInstaller) DBPort() string { + return ins.dbPort +} diff --git a/install/install/pgsql.go b/install/install/pgsql.go new file mode 100644 index 00000000..ed18e4cf --- /dev/null +++ b/install/install/pgsql.go @@ -0,0 +1,117 @@ +/* +* +* Gosora PostgreSQL Interface +* Under heavy development +* Copyright Azareal 2017 - 2018 +* + */ +package install + +import ( + "database/sql" + "errors" + "fmt" + "strings" + + "../../query_gen/lib" + _ "github.com/go-sql-driver/mysql" +) + +// We don't need SSL to run an installer... Do we? +var dbSslmode = "disable" + +func init() { + adapters["pgsql"] = &PgsqlInstaller{dbHost: ""} +} + +type PgsqlInstaller struct { + db *sql.DB + dbHost string + dbUsername string + dbPassword string + dbName string + dbPort string +} + +func (ins *PgsqlInstaller) SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) { + ins.dbHost = dbHost + ins.dbUsername = dbUsername + ins.dbPassword = dbPassword + ins.dbName = dbName + ins.dbPort = dbPort +} + +func (ins *PgsqlInstaller) Name() string { + return "pgsql" +} + +func (ins *PgsqlInstaller) DefaultPort() string { + return "5432" +} + +func (ins *PgsqlInstaller) InitDatabase() (err error) { + _dbPassword := ins.dbPassword + if _dbPassword != "" { + _dbPassword = " password=" + pgEscapeBit(_dbPassword) + } + db, err := sql.Open("postgres", "host='"+pgEscapeBit(ins.dbHost)+"' port='"+pgEscapeBit(ins.dbPort)+"' user='"+pgEscapeBit(ins.dbUsername)+"' dbname='"+pgEscapeBit(ins.dbName)+"'"+_dbPassword+" sslmode='"+dbSslmode+"'") + if err != nil { + return err + } + + // Make sure that the connection is alive.. + err = db.Ping() + if err != nil { + return err + } + fmt.Println("Successfully connected to the database") + + // TODO: Create the database, if it doesn't exist + + // Ready the query builder + qgen.Builder.SetConn(db) + err = qgen.Builder.SetAdapter("pgsql") + if err != nil { + return err + } + ins.db = db + + return nil +} + +func (ins *PgsqlInstaller) TableDefs() (err error) { + return errors.New("TableDefs() not implemented") +} + +func (ins *PgsqlInstaller) InitialData() (err error) { + return errors.New("InitialData() not implemented") +} + +func (ins *PgsqlInstaller) CreateAdmin() error { + return createAdmin() +} + +func (ins *PgsqlInstaller) DBHost() string { + return ins.dbHost +} + +func (ins *PgsqlInstaller) DBUsername() string { + return ins.dbUsername +} + +func (ins *PgsqlInstaller) DBPassword() string { + return ins.dbPassword +} + +func (ins *PgsqlInstaller) DBName() string { + return ins.dbName +} + +func (ins *PgsqlInstaller) DBPort() string { + return ins.dbPort +} + +func pgEscapeBit(bit string) string { + // TODO: Write a custom parser, so that backslashes work properly in the sql.Open string. Do something similar for the database driver, if possible? + return strings.Replace(bit, "'", "\\'", -1) +} diff --git a/install/utils.go b/install/install/utils.go similarity index 95% rename from install/utils.go rename to install/install/utils.go index 770bb338..25253ead 100644 --- a/install/utils.go +++ b/install/install/utils.go @@ -1,9 +1,11 @@ -package main +package install import "encoding/base64" import "crypto/rand" import "golang.org/x/crypto/bcrypt" +const saltLength int = 32 + // Generate a cryptographically secure set of random bytes.. func GenerateSafeString(length int) (string, error) { rb := make([]byte, length) diff --git a/install/pgsql.go b/install/pgsql.go deleted file mode 100644 index 03bee8b0..00000000 --- a/install/pgsql.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -* -* Gosora PostgreSQL Interface -* Under heavy development -* Copyright Azareal 2017 - 2018 -* - */ -package main - -import "fmt" -import "strings" -import "database/sql" -import _ "github.com/go-sql-driver/mysql" - -// We don't need SSL to run an installer... Do we? -var dbSslmode = "disable" - -func _setPgsqlAdapter() { - dbPort = "5432" - initDatabase = _initPgsql -} - -func _initPgsql() (err error) { - _dbPassword := dbPassword - if _dbPassword != "" { - _dbPassword = " password=" + _pgEscapeBit(_dbPassword) - } - db, err = sql.Open("postgres", "host='"+_pgEscapeBit(dbHost)+"' port='"+_pgEscapeBit(dbPort)+"' user='"+_pgEscapeBit(dbUsername)+"' dbname='"+_pgEscapeBit(dbName)+"'"+_dbPassword+" sslmode='"+dbSslmode+"'") - if err != nil { - return err - } - fmt.Println("Successfully connected to the database") - - // TODO: Create the database, if it doesn't exist - - return nil -} - -func _pgEscapeBit(bit string) string { - // TODO: Write a custom parser, so that backslashes work properly in the sql.Open string. Do something similar for the database driver, if possible? - return strings.Replace(bit, "'", "\\'", -1) -} diff --git a/main.go b/main.go index 5f0e059f..3f67117b 100644 --- a/main.go +++ b/main.go @@ -46,7 +46,7 @@ type StringList []string var allowedFileExts = StringList{ "png", "jpg", "jpeg", "svg", "bmp", "gif", "tif", "webp", "apng", // images - "txt", "xml", "json", "yaml", "toml", "ini", "md", "html", "rtf", "js", "py", "rb", "css", "scss", "less", "java", "ts", "cs", "c", "cc", "cpp", "cxx", "C", "c++", "h", "hh", "hpp", "hxx", "h++", "rs", "rlib", "htaccess", "gitignore", // text + "txt", "xml", "json", "yaml", "toml", "ini", "md", "html", "rtf", "js", "py", "rb", "css", "scss", "less", "eqcss", "java", "ts", "cs", "c", "cc", "cpp", "cxx", "C", "c++", "h", "hh", "hpp", "hxx", "h++", "rs", "rlib", "htaccess", "gitignore", // text "mp3", "mp4", "avi", "wmv", "webm", // video @@ -92,7 +92,10 @@ func main() { startTime = time.Now() log.Print("Processing configuration data") - processConfig() + err = processConfig() + if err != nil { + log.Fatal(err) + } err = initThemes() if err != nil { diff --git a/mod_routes.go b/mod_routes.go index 7bc9c461..21a5ad27 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -4,7 +4,6 @@ import ( //"log" //"fmt" "html" - "log" "net" "net/http" "strconv" @@ -48,8 +47,6 @@ func routeEditTopic(w http.ResponseWriter, r *http.Request, user User) { topicName := r.PostFormValue("topic_name") topicContent := html.EscapeString(r.PostFormValue("topic_content")) - log.Print("topicContent ", topicContent) - err = topic.Update(topicName, topicContent) if err != nil { InternalErrorJSQ(err, w, r, isJs) diff --git a/mssql.go b/mssql.go new file mode 100644 index 00000000..637a3ea0 --- /dev/null +++ b/mssql.go @@ -0,0 +1,84 @@ +// +build mssql + +/* +* +* Gosora MSSQL Interface +* Copyright Azareal 2016 - 2018 +* + */ +package main + +//import "time" +import ( + "database/sql" + "net/url" + + "./query_gen/lib" + _ "github.com/denisenkom/go-mssqldb" +) + +var dbInstance string = "" + +var getActivityFeedByWatcherStmt *sql.Stmt +var getActivityCountByWatcherStmt *sql.Stmt +var todaysPostCountStmt *sql.Stmt +var todaysTopicCountStmt *sql.Stmt +var todaysReportCountStmt *sql.Stmt +var todaysNewUserCountStmt *sql.Stmt +var findUsersByIPUsersStmt *sql.Stmt +var findUsersByIPTopicsStmt *sql.Stmt +var findUsersByIPRepliesStmt *sql.Stmt + +func init() { + dbAdapter = "mssql" + _initDatabase = initMSSQL +} + +func initMSSQL() (err error) { + // TODO: Move this bit to the query gen lib + query := url.Values{} + query.Add("database", dbConfig.Dbname) + u := &url.URL{ + Scheme: "sqlserver", + User: url.UserPassword(dbConfig.Username, dbConfig.Password), + Host: dbConfig.Host + ":" + dbConfig.Port, + Path: dbInstance, + RawQuery: query.Encode(), + } + db, err = sql.Open("mssql", u.String()) + if err != nil { + return err + } + + // Make sure that the connection is alive + err = db.Ping() + if err != nil { + return err + } + + // TODO: Fetch the database version + + // Set the number of max open connections + db.SetMaxOpenConns(64) + db.SetMaxIdleConns(32) + + // Only hold connections open for five seconds to avoid accumulating a large number of stale connections + //db.SetConnMaxLifetime(5 * time.Second) + + // Build the generated prepared statements, we are going to slowly move the queries over to the query generator rather than writing them all by hand, this'll make it easier for us to implement database adapters for other databases like PostgreSQL, MSSQL, SQlite, etc. + err = _gen_mssql() + if err != nil { + return err + } + + // Ready the query builder + qgen.Builder.SetConn(db) + err = qgen.Builder.SetAdapter("mssql") + if err != nil { + return err + } + + // TODO: Add the custom queries + + return nil +} diff --git a/mysql.go b/mysql.go index 948109bf..08a2a3e9 100644 --- a/mysql.go +++ b/mysql.go @@ -1,4 +1,4 @@ -// +build !pgsql !sqlite !mssql +// +build !pgsql, !sqlite, !mssql /* * @@ -28,16 +28,18 @@ var findUsersByIPRepliesStmt *sql.Stmt func init() { dbAdapter = "mysql" + _initDatabase = initMySQL } -func _initDatabase() (err error) { +func initMySQL() (err error) { var _dbpassword string if dbConfig.Password != "" { _dbpassword = ":" + dbConfig.Password } + // TODO: Move this bit to the query gen lib // Open the database connection - db, err = sql.Open("mysql", dbConfig.Username+_dbpassword+"@tcp("+dbConfig.Host+":"+dbConfig.Port+")/"+dbConfig.Dbname+"?collation="+dbCollation) + db, err = sql.Open("mysql", dbConfig.Username+_dbpassword+"@tcp("+dbConfig.Host+":"+dbConfig.Port+")/"+dbConfig.Dbname+"?collation="+dbCollation+"&parseTime=true") if err != nil { return err } diff --git a/mysql.sql b/mysql.sql deleted file mode 100644 index 28eff700..00000000 --- a/mysql.sql +++ /dev/null @@ -1,269 +0,0 @@ -CREATE TABLE `users_groups`( - `gid` int not null AUTO_INCREMENT, - `name` varchar(100) not null, - `permissions` text not null, - `plugin_perms` text not null, - `is_mod` tinyint DEFAULT 0 not null, - `is_admin` tinyint DEFAULT 0 not null, - `is_banned` tinyint DEFAULT 0 not null, - `tag` varchar(50) DEFAULT '' not null, - primary key(`gid`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `emails`( - `email` varchar(200) not null, - `uid` int not null, - `validated` tinyint DEFAULT 0 not null, - `token` varchar(200) DEFAULT '' not null -); - -CREATE TABLE `forums`( - `fid` int not null AUTO_INCREMENT, - `name` varchar(100) not null, - `desc` varchar(200) not null, - `active` tinyint DEFAULT 1 not null, - `topicCount` int DEFAULT 0 not null, - `preset` varchar(100) DEFAULT '' not null, - `parentID` int DEFAULT 0 not null, /* TODO: Add support for subforums */ - `parentType` varchar(50) DEFAULT '' not null, - `lastTopicID` int DEFAULT 0 not null, - `lastReplyerID` int DEFAULT 0 not null, - primary key(`fid`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `forums_permissions`( - `fid` int not null, - `gid` int not null, - `preset` varchar(100) DEFAULT '' not null, - `permissions` text not null, - primary key(fid, gid) -); - -CREATE TABLE `topics`( - `tid` int not null AUTO_INCREMENT, - `title` varchar(100) not null, - `content` text not null, - `parsed_content` text not null, - `createdAt` datetime not null, - `lastReplyAt` datetime not null, - `lastReplyBy` int not null, - `createdBy` int not null, - `is_closed` tinyint DEFAULT 0 not null, - `sticky` tinyint DEFAULT 0 not null, - `parentID` int DEFAULT 2 not null, - `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, - `postCount` int DEFAULT 1 not null, - `likeCount` int DEFAULT 0 not null, - `words` int DEFAULT 0 not null, - `css_class` varchar(100) DEFAULT '' not null, - `data` varchar(200) DEFAULT '' not null, - primary key(`tid`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `replies`( - `rid` int not null AUTO_INCREMENT, - `tid` int not null, - `content` text not null, - `parsed_content` text not null, - `createdAt` datetime not null, - `createdBy` int not null, - `lastEdit` int not null, - `lastEditBy` int not null, /* Do we need this? */ - /*`editIndex` int not null,*/ /* For append edits, e.g. auto-merges? Is this enough for this feature? */ - `lastUpdated` datetime not null, - `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, - `likeCount` int DEFAULT 0 not null, - `words` int DEFAULT 1 not null, - `actionType` varchar(20) DEFAULT '' not null, - primary key(`rid`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `attachments`( - `attachID` int not null AUTO_INCREMENT, - `sectionID` int DEFAULT 0 not null, /* section ID */ - `sectionTable` varchar(200) DEFAULT 'forums' not null, /* section table */ - `originID` int not null, - `originTable` varchar(200) DEFAULT 'replies' not null, - `uploadedBy` int not null, - `path` varchar(200) not null, - primary key(`attachID`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `revisions`( - `index` int not null, - `content` text not null, - `contentID` int not null, - `contentType` varchar(100) DEFAULT 'replies' not null -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `users_replies`( - `rid` int not null AUTO_INCREMENT, - `uid` int not null, - `content` text not null, - `parsed_content` text not null, - `createdAt` datetime not null, - `createdBy` int not null, - `lastEdit` int not null, - `lastEditBy` int not null, - `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, - primary key(`rid`) -) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; - -CREATE TABLE `likes`( - `weight` tinyint DEFAULT 1 not null, - /*`type` tinyint not null, /* Regular Post: 1, Big Post: 2, Mega Post: 3, etc.*/ - `targetItem` int not null, - `targetType` varchar(50) DEFAULT 'replies' not null, - `sentBy` int not null, - `recalc` tinyint DEFAULT 0 not null -); - -CREATE TABLE `activity_stream_matches`( - `watcher` int not null, - `asid` int not null -); - -CREATE TABLE `activity_stream`( - `asid` int not null AUTO_INCREMENT, - `actor` int not null, /* the one doing the act */ - `targetUser` int not null, /* the user who created the item the actor is acting on, some items like forums may lack a targetUser field */ - `event` varchar(50) not null, /* mention, like, reply (as in the act of replying to an item, not the reply item type, you can "reply" to a forum by making a topic in it), friend_invite */ - `elementType` varchar(50) not null, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */ - `elementID` int not null, /* the ID of the element being acted upon */ - primary key(`asid`) -); - -CREATE TABLE `activity_subscriptions`( - `user` int not null, - `targetID` int not null, /* the ID of the element being acted upon */ - `targetType` varchar(50) not null, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */ - `level` tinyint DEFAULT 0 not null /* 0: Mentions (aka the global default for any post), 1: Replies To You, 2: All Replies*/ -); - -/* Due to MySQL's design, we have to drop the unique keys for table settings, plugins, and themes down from 200 to 180 or it will error */ -CREATE TABLE `settings`( - `name` varchar(180) not null, - `content` varchar(250) not null, - `type` varchar(50) not null, - `constraints` varchar(200) DEFAULT '' not null, - unique(`name`) -); - -CREATE TABLE `plugins`( - `uname` varchar(180) not null, - `active` tinyint DEFAULT 0 not null, - `installed` tinyint DEFAULT 0 not null, - unique(`uname`) -); - -CREATE TABLE `themes`( - `uname` varchar(180) not null, - `default` tinyint DEFAULT 0 not null, - unique(`uname`) -); - -CREATE TABLE `widgets`( - `position` int not null, - `side` varchar(100) not null, - `type` varchar(100) not null, - `active` tinyint(1) DEFAULT 0 not null, - `location` varchar(100) not null, - `data` text DEFAULT '' not null -); - -CREATE TABLE `moderation_logs`( - `action` varchar(100) not null, - `elementID` int not null, - `elementType` varchar(100) not null, - `ipaddress` varchar(200) not null, - `actorID` int not null, - `doneAt` datetime not null -); - -CREATE TABLE `administration_logs`( - `action` varchar(100) not null, - `elementID` int not null, - `elementType` varchar(100) not null, - `ipaddress` varchar(200) not null, - `actorID` int not null, - `doneAt` datetime not null -); - -INSERT INTO sync(`last_update`) VALUES (UTC_TIMESTAMP()); - -INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool'); -INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3'); -INSERT INTO settings(`name`,`content`,`type`) VALUES ('bigpost_min_words','250','int'); -INSERT INTO settings(`name`,`content`,`type`) VALUES ('megapost_min_words','1000','int'); -INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1); -INSERT INTO emails(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1); - -/* -The Permissions: - -Global Permissions: -BanUsers -ActivateUsers -EditUser -EditUserEmail -EditUserPassword -EditUserGroup -EditUserGroupSuperMod -EditUserGroupAdmin -EditGroup -EditGroupLocalPerms -EditGroupGlobalPerms -EditGroupSuperMod -EditGroupAdmin -ManageForums -EditSettings -ManageThemes -ManagePlugins -ViewAdminLogs -ViewIPs - -Non-staff Global Permissions: -UploadFiles - -Forum Permissions: -ViewTopic -LikeItem -CreateTopic -EditTopic -DeleteTopic -CreateReply -EditReply -DeleteReply -PinTopic -CloseTopic -*/ - -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,1,"Admin"); -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,"Mod"); -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`) VALUES ('Member','{"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`is_banned`) VALUES ('Banned','{"ViewTopic":true}','{}',1); -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}'); -INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest'); - -INSERT INTO forums(`name`,`active`) VALUES ('Reports',0); -INSERT INTO forums(`name`,`lastTopicID`,`lastReplyerID`) VALUES ("General",1,1); - -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,1,'{}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (4,1,'{}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (5,1,'{}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (6,1,'{}'); - -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (4,2,'{"ViewTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (5,2,'{"ViewTopic":true}'); -INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (6,2,'{"ViewTopic":true}'); - -INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`createdBy`,`parentID`) -VALUES ('Test Topic','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2); - -INSERT INTO replies(`tid`,`content`,`createdAt`,`createdBy`,`lastEdit`,`lastEditBy`) -VALUES (1,'Reply 1',UTC_TIMESTAMP(),1,0,0); diff --git a/pgsql.go b/pgsql.go index a3b76d09..446e1966 100644 --- a/pgsql.go +++ b/pgsql.go @@ -5,6 +5,7 @@ package main import "strings" + //import "time" import "database/sql" import _ "github.com/lib/pq" @@ -21,15 +22,17 @@ var todays_newuser_count_stmt *sql.Stmt func init() { db_adapter = "pgsql" + _initDatabase = initPgsql } -func _init_database() (err error) { +func initPgsql() (err error) { // TODO: Investigate connect_timeout to see what it does exactly and whether it's relevant to us var _dbpassword string - if(dbpassword != ""){ + if dbpassword != "" { _dbpassword = " password='" + _escape_bit(db_config.Password) + "'" } - db, err = sql.Open("postgres", "host='" + _escape_bit(db_config.Host) + "' port='" + _escape_bit(db_config.Port) + "' user='" + _escape_bit(db_config.Username) + "' dbname='" + _escape_bit(config.Dbname) + "'" + _dbpassword + " sslmode='" + db_sslmode + "'") + // TODO: Move this bit to the query gen lib + db, err = sql.Open("postgres", "host='"+_escape_bit(db_config.Host)+"' port='"+_escape_bit(db_config.Port)+"' user='"+_escape_bit(db_config.Username)+"' dbname='"+_escape_bit(config.Dbname)+"'"+_dbpassword+" sslmode='"+db_sslmode+"'") if err != nil { return err } @@ -69,5 +72,5 @@ func _init_database() (err error) { func _escape_bit(bit string) string { // TODO: Write a custom parser, so that backslashes work properly in the sql.Open string. Do something similar for the database driver, if possible? - return strings.Replace(bit,"'","\\'",-1) + return strings.Replace(bit, "'", "\\'", -1) } diff --git a/plugin_bbcode.go b/plugin_bbcode.go index a3325270..26e18d0b 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -388,20 +388,18 @@ func bbcodeFullParse(msg string) string { } } } - //log.Print(string(outbytes)) + //log.Print("Outbytes:",`"`+string(outbytes)+`"`) if lastTag != i { outbytes = append(outbytes, msgbytes[lastTag:]...) - //log.Print("Outbytes:",`"`+string(outbytes)+`"`) - //log.Print("----") } if len(outbytes) != 0 { //log.Print("BBCode Post:",`"`+string(outbytes[0:len(outbytes) - 10])+`"`) - //log.Print("----") msg = string(outbytes[0 : len(outbytes)-10]) } else { msg = string(msgbytes[0 : len(msgbytes)-10]) } + //log.Print("----") //msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") msg = bbcodeURLLabel.ReplaceAllString(msg, "$4") diff --git a/plugin_socialgroups.go b/plugin_socialgroups.go index 4f8651bd..c0315ddb 100644 --- a/plugin_socialgroups.go +++ b/plugin_socialgroups.go @@ -478,7 +478,7 @@ func socialgroupsMemberList(w http.ResponseWriter, r *http.Request, user User) { } else { sgMember.User.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(sgMember.User.ID), 1) } - sgMember.JoinedAt, _ = relativeTime(sgMember.JoinedAt) + sgMember.JoinedAt, _ = relativeTimeFromString(sgMember.JoinedAt) if sgItem.Owner == sgMember.User.ID { sgMember.RankString = "Owner" } else { diff --git a/plugin_test.go b/plugin_test.go index 87936d3a..910b5a91 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -16,6 +16,11 @@ func addMEPair(msgList []MEPair, msg string, expects string) []MEPair { func TestBBCodeRender(t *testing.T) { //t.Skip() + err := initBbcode() + if err != nil { + t.Fatal(err) + } + var res string var msgList []MEPair msgList = addMEPair(msgList, "hi", "hi") @@ -54,8 +59,8 @@ func TestBBCodeRender(t *testing.T) { } } - var msg, expects string - var err error + var msg string + var expects string msg = "[rand][/rand]" expects = "[Invalid Number][rand][/rand]" diff --git a/query_gen/lib/install.go b/query_gen/lib/install.go index 2f2e8ce0..2c5d638a 100644 --- a/query_gen/lib/install.go +++ b/query_gen/lib/install.go @@ -26,11 +26,13 @@ func (install *installer) SetAdapter(name string) error { return err } install.adapter = adap + install.instructions = []DB_Install_Instruction{} return nil } func (install *installer) SetAdapterInstance(adapter DB_Adapter) { install.adapter = adapter + install.instructions = []DB_Install_Instruction{} } func (install *installer) CreateTable(table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) error { @@ -42,6 +44,15 @@ func (install *installer) CreateTable(table string, charset string, collation st return nil } +func (install *installer) SimpleInsert(table string, columns string, fields string) error { + res, err := install.adapter.SimpleInsert("_installer", table, columns, fields) + if err != nil { + return err + } + install.instructions = append(install.instructions, DB_Install_Instruction{table, res, "insert"}) + return nil +} + func (install *installer) Write() error { var inserts string // We can't escape backticks, so we have to dump it out a file at a time @@ -52,7 +63,7 @@ func (install *installer) Write() error { return err } } else { - inserts += instr.Contents + "\n" + inserts += instr.Contents + ";\n" } } return writeFile("./schema/"+install.adapter.GetName()+"/inserts.sql", inserts) diff --git a/query_gen/lib/mysql.go b/query_gen/lib/mysql.go index 7f2a69b3..f39e95fd 100644 --- a/query_gen/lib/mysql.go +++ b/query_gen/lib/mysql.go @@ -134,6 +134,13 @@ func (adapter *Mysql_Adapter) SimpleInsert(name string, table string, columns st querystr += ") VALUES (" for _, field := range processFields(fields) { + nameLen := len(field.Name) + if field.Name[0] == '"' && field.Name[nameLen-1] == '"' && nameLen >= 3 { + field.Name = "'" + field.Name[1:nameLen-1] + "'" + } + if field.Name[0] == '\'' && field.Name[nameLen-1] == '\'' && nameLen >= 3 { + field.Name = "'" + strings.Replace(field.Name[1:nameLen-1], "'", "''", -1) + "'" + } querystr += field.Name + "," } querystr = querystr[0 : len(querystr)-1] @@ -330,6 +337,7 @@ func (adapter *Mysql_Adapter) SimpleSelect(name string, table string, columns st if len(orderby) != 0 { querystr += " ORDER BY " for _, column := range processOrderby(orderby) { + // TODO: We might want to escape this column querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } querystr = querystr[0 : len(querystr)-1] @@ -778,12 +786,12 @@ func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where strin var querystr = "SELECT COUNT(*) AS `count` FROM `" + table + "`" - // Add support for BETWEEN x.x + // TODO: Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" //fmt.Println("SimpleCount:",name) //fmt.Println("where:",where) - //fmt.Println("_process_where:",_process_where(where)) + //fmt.Println("processWhere:",processWhere(where)) for _, loc := range processWhere(where) { for _, token := range loc.Expr { switch token.Type { @@ -814,6 +822,9 @@ func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where strin func (adapter *Mysql_Adapter) Write() error { var stmts, body string for _, name := range adapter.BufferOrder { + if name[0] == '_' { + continue + } stmt := adapter.Buffer[name] // TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :( if stmt.Type != "create-table" { @@ -828,7 +839,7 @@ func (adapter *Mysql_Adapter) Write() error { } } - out := `// +build !pgsql !sqlite !mssql + out := `// +build !pgsql, !sqlite, !mssql /* This file was generated by Gosora's Query Generator. Please try to avoid modifying this file, as it might change at any time. */ diff --git a/query_gen/lib/pgsql.go b/query_gen/lib/pgsql.go index 1c74ce2a..e1214291 100644 --- a/query_gen/lib/pgsql.go +++ b/query_gen/lib/pgsql.go @@ -304,6 +304,9 @@ func (adapter *Pgsql_Adapter) SimpleCount(name string, table string, where strin func (adapter *Pgsql_Adapter) Write() error { var stmts, body string for _, name := range adapter.BufferOrder { + if name[0] == '_' { + continue + } stmt := adapter.Buffer[name] // TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :( if stmt.Type != "create-table" { diff --git a/query_gen/lib/querygen.go b/query_gen/lib/querygen.go index f9bbdd10..fac57e1f 100644 --- a/query_gen/lib/querygen.go +++ b/query_gen/lib/querygen.go @@ -6,102 +6,91 @@ import "errors" var DB_Registry []DB_Adapter var No_Adapter = errors.New("This adapter doesn't exist") -type DB_Table_Column struct -{ - Name string - Type string - Size int - Null bool +type DB_Table_Column struct { + Name string + Type string + Size int + Null bool Auto_Increment bool - Default string + Default string } -type DB_Table_Key struct -{ +type DB_Table_Key struct { Columns string - Type string + Type string } -type DB_Select struct -{ - Table string +type DB_Select struct { + Table string Columns string - Where string + Where string Orderby string - Limit string + Limit string } -type DB_Join struct -{ - Table1 string - Table2 string +type DB_Join struct { + Table1 string + Table2 string Columns string Joiners string - Where string + Where string Orderby string - Limit string + Limit string } -type DB_Insert struct -{ - Table string +type DB_Insert struct { + Table string Columns string - Fields string + Fields string } -type DB_Column struct -{ +type DB_Column struct { Table string - Left string // Could be a function or a column, so I'm naming this Left + Left string // Could be a function or a column, so I'm naming this Left Alias string // aka AS Blah, if it's present - Type string // function or column + Type string // function or column } -type DB_Field struct -{ +type DB_Field struct { Name string Type string } -type DB_Where struct -{ +type DB_Where struct { Expr []DB_Token // Simple expressions, the innards of functions are opaque for now. } -type DB_Joiner struct -{ - LeftTable string - LeftColumn string - RightTable string +type DB_Joiner struct { + LeftTable string + LeftColumn string + RightTable string RightColumn string - Operator string + Operator string } -type DB_Order struct -{ +type DB_Order struct { Column string - Order string + Order string } type DB_Token struct { Contents string - Type string // function, operator, column, number, string, substitute + Type string // function, operator, column, number, string, substitute } type DB_Setter struct { Column string - Expr []DB_Token // Simple expressions, the innards of functions are opaque for now. + Expr []DB_Token // Simple expressions, the innards of functions are opaque for now. } type DB_Limit struct { - Offset string // ? or int + Offset string // ? or int MaxCount string // ? or int } -type DB_Stmt struct -{ +type DB_Stmt struct { Contents string - Type string // create-table, insert, update, delete + Type string // create-table, insert, update, delete } type DB_Adapter interface { @@ -114,13 +103,13 @@ type DB_Adapter interface { Purge(name string, table string) (string, error) SimpleSelect(name string, table string, columns string, where string, orderby string, limit string) (string, error) SimpleLeftJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) - SimpleInnerJoin(string,string,string,string,string,string,string,string) (string, error) - SimpleInsertSelect(string,DB_Insert,DB_Select) (string,error) - SimpleInsertLeftJoin(string,DB_Insert,DB_Join) (string,error) - SimpleInsertInnerJoin(string,DB_Insert,DB_Join) (string,error) - SimpleCount(string,string,string,string) (string, error) + SimpleInnerJoin(string, string, string, string, string, string, string, string) (string, error) + SimpleInsertSelect(string, DB_Insert, DB_Select) (string, error) + SimpleInsertLeftJoin(string, DB_Insert, DB_Join) (string, error) + SimpleInsertInnerJoin(string, DB_Insert, DB_Join) (string, error) + SimpleCount(string, string, string, string) (string, error) Write() error - + // TODO: Add a simple query builder } diff --git a/query_gen/main.go b/query_gen/main.go index 07fd689e..53595876 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -120,6 +120,22 @@ func create_tables(adapter qgen.DB_Adapter) error { }, ) + qgen.Install.CreateTable("users_groups", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"gid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"name", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"permissions", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"plugin_perms", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"is_mod", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"is_admin", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"is_banned", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"tag", "varchar", 50, false, false, "''"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"gid", "primary"}, + }, + ) + // What should we do about global penalties? Put them on the users table for speed? Or keep them here? // Should we add IP Penalties? No, that's a stupid idea, just implement IP Bans properly. What about shadowbans? // TODO: Perm overrides @@ -166,6 +182,191 @@ func create_tables(adapter qgen.DB_Adapter) error { }, ) + qgen.Install.CreateTable("emails", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"email", "varchar", 200, false, false, ""}, + qgen.DB_Table_Column{"uid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"validated", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"token", "varchar", 200, false, false, "''"}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("forums", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"fid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"name", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"desc", "varchar", 200, false, false, ""}, + qgen.DB_Table_Column{"active", "boolean", 0, false, false, "1"}, + qgen.DB_Table_Column{"topicCount", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"preset", "varchar", 100, false, false, "''"}, + qgen.DB_Table_Column{"parentID", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"parentType", "varchar", 50, false, false, "''"}, + qgen.DB_Table_Column{"lastTopicID", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"lastReplyerID", "int", 0, false, false, "0"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"fid", "primary"}, + }, + ) + + qgen.Install.CreateTable("forums_permissions", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"fid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"gid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"preset", "varchar", 100, false, false, "''"}, + qgen.DB_Table_Column{"permissions", "text", 0, false, false, ""}, + }, + []qgen.DB_Table_Key{ + // TODO: Test to see that the compound primary key works + qgen.DB_Table_Key{"fid,gid", "primary"}, + }, + ) + + qgen.Install.CreateTable("topics", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"tid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"title", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"parsed_content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"createdAt", "createdAt", 0, false, false, ""}, + qgen.DB_Table_Column{"lastReplyAt", "datetime", 0, false, false, ""}, + qgen.DB_Table_Column{"lastReplyBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"createdBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"is_closed", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"sticky", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"parentID", "int", 0, false, false, "2"}, + qgen.DB_Table_Column{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"}, + qgen.DB_Table_Column{"postCount", "int", 0, false, false, "1"}, + qgen.DB_Table_Column{"likeCount", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"words", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"css_class", "varchar", 100, false, false, "''"}, + qgen.DB_Table_Column{"data", "varchar", 200, false, false, "''"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"tid", "primary"}, + }, + ) + + qgen.Install.CreateTable("replies", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"rid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"tid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"parsed_content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"createdAt", "createdAt", 0, false, false, ""}, + qgen.DB_Table_Column{"createdBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"lastEdit", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"lastEditBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"lastUpdated", "datetime", 0, false, false, ""}, + qgen.DB_Table_Column{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"}, + qgen.DB_Table_Column{"likeCount", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"words", "int", 0, false, false, "1"}, // ? - replies has a default of 1 and topics has 0? why? + qgen.DB_Table_Column{"actionType", "varchar", 20, false, false, "''"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"rid", "primary"}, + }, + ) + + qgen.Install.CreateTable("attachments", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"attachID", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"sectionID", "int", 0, false, false, "0"}, + qgen.DB_Table_Column{"sectionTable", "varchar", 200, false, false, "forums"}, + qgen.DB_Table_Column{"originID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"originTable", "varchar", 200, false, false, "replies"}, + qgen.DB_Table_Column{"uploadedBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"path", "varchar", 200, false, false, ""}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"attachID", "primary"}, + }, + ) + + qgen.Install.CreateTable("revisions", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"index", "int", 0, false, false, ""}, // TODO: Replace this with a proper revision ID x.x + qgen.DB_Table_Column{"content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"contentID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"contentType", "varchar", 100, false, false, "replies"}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("users_replies", "utf8mb4", "utf8mb4_general_ci", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"rid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"uid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"parsed_content", "text", 0, false, false, ""}, + qgen.DB_Table_Column{"createdAt", "createdAt", 0, false, false, ""}, + qgen.DB_Table_Column{"createdBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"lastEdit", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"lastEditBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"rid", "primary"}, + }, + ) + + qgen.Install.CreateTable("likes", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"weight", "tinyint", 0, false, false, "1"}, + qgen.DB_Table_Column{"targetItem", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"targetType", "varchar", 50, false, false, "replies"}, + qgen.DB_Table_Column{"sentBy", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"recalc", "tinyint", 0, false, false, "0"}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("activity_stream_matches", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"watcher", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"asid", "int", 0, false, false, ""}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("activity_stream", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"asid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"actor", "int", 0, false, false, ""}, /* the one doing the act */ + qgen.DB_Table_Column{"targetUser", "int", 0, false, false, ""}, /* the user who created the item the actor is acting on, some items like forums may lack a targetUser field */ + qgen.DB_Table_Column{"event", "varchar", 50, false, false, ""}, /* mention, like, reply (as in the act of replying to an item, not the reply item type, you can "reply" to a forum by making a topic in it), friend_invite */ + qgen.DB_Table_Column{"elementType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */ + qgen.DB_Table_Column{"elementID", "int", 0, false, false, ""}, /* the ID of the element being acted upon */ + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"asid", "primary"}, + }, + ) + + qgen.Install.CreateTable("activity_subscriptions", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"user", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"targetID", "int", 0, false, false, ""}, /* the ID of the element being acted upon */ + qgen.DB_Table_Column{"targetType", "varchar", 50, false, false, ""}, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */ + qgen.DB_Table_Column{"level", "int", 0, false, false, "0"}, /* 0: Mentions (aka the global default for any post), 1: Replies To You, 2: All Replies*/ + }, + []qgen.DB_Table_Key{}, + ) + + /* Due to MySQL's design, we have to drop the unique keys for table settings, plugins, and themes down from 200 to 180 or it will error */ + qgen.Install.CreateTable("settings", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"name", "varchar", 180, false, false, ""}, + qgen.DB_Table_Column{"content", "varchar", 250, false, false, ""}, + qgen.DB_Table_Column{"type", "varchar", 50, false, false, ""}, + qgen.DB_Table_Column{"constraints", "varchar", 200, false, false, "''"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"name", "unique"}, + }, + ) + qgen.Install.CreateTable("word_filters", "", "", []qgen.DB_Table_Column{ qgen.DB_Table_Column{"wfid", "int", 0, false, true, ""}, @@ -177,6 +378,63 @@ func create_tables(adapter qgen.DB_Adapter) error { }, ) + qgen.Install.CreateTable("plugins", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"uname", "varchar", 180, false, false, ""}, + qgen.DB_Table_Column{"active", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"installed", "boolean", 0, false, false, "0"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"uname", "unique"}, + }, + ) + + qgen.Install.CreateTable("themes", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"uname", "varchar", 180, false, false, ""}, + qgen.DB_Table_Column{"default", "boolean", 0, false, false, "0"}, + }, + []qgen.DB_Table_Key{ + qgen.DB_Table_Key{"uname", "unique"}, + }, + ) + + qgen.Install.CreateTable("widgets", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"position", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"side", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"type", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"active", "boolean", 0, false, false, "0"}, + qgen.DB_Table_Column{"location", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"data", "text", 0, false, false, "''"}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("moderation_logs", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"action", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"elementID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"elementType", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"ipaddress", "varchar", 200, false, false, ""}, + qgen.DB_Table_Column{"actorID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"doneAt", "datetime", 0, false, false, ""}, + }, + []qgen.DB_Table_Key{}, + ) + + qgen.Install.CreateTable("administration_logs", "", "", + []qgen.DB_Table_Column{ + qgen.DB_Table_Column{"action", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"elementID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"elementType", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"ipaddress", "varchar", 200, false, false, ""}, + qgen.DB_Table_Column{"actorID", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"doneAt", "datetime", 0, false, false, ""}, + }, + []qgen.DB_Table_Key{}, + ) + qgen.Install.CreateTable("sync", "", "", []qgen.DB_Table_Column{ qgen.DB_Table_Column{"last_update", "datetime", 0, false, false, ""}, @@ -189,6 +447,103 @@ func create_tables(adapter qgen.DB_Adapter) error { // nolint func seed_tables(adapter qgen.DB_Adapter) error { + qgen.Install.SimpleInsert("sync", "last_update", "UTC_TIMESTAMP()") + + qgen.Install.SimpleInsert("settings", "name, content, type", "'url_tags','1','bool'") + qgen.Install.SimpleInsert("settings", "name, content, type, constraints", "'activation_type','1','list','1-3'") + qgen.Install.SimpleInsert("settings", "name, content, type", "'bigpost_min_words','250','int'") + qgen.Install.SimpleInsert("settings", "name, content, type", "'megapost_min_words','1000','int'") + qgen.Install.SimpleInsert("themes", "uname, default", "'tempra-simple',1") + qgen.Install.SimpleInsert("emails", "email, uid, validated", "'admin@localhost',1,1") // ? - Use a different default email or let the admin input it during installation? + + /* + The Permissions: + + Global Permissions: + BanUsers + ActivateUsers + EditUser + EditUserEmail + EditUserPassword + EditUserGroup + EditUserGroupSuperMod + EditUserGroupAdmin + EditGroup + EditGroupLocalPerms + EditGroupGlobalPerms + EditGroupSuperMod + EditGroupAdmin + ManageForums + EditSettings + ManageThemes + ManagePlugins + ViewAdminLogs + ViewIPs + + Non-staff Global Permissions: + UploadFiles + + Forum Permissions: + ViewTopic + LikeItem + CreateTopic + EditTopic + DeleteTopic + CreateReply + EditReply + DeleteReply + PinTopic + CloseTopic + */ + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, tag", `'Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,1,"Admin"`) + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, tag", `'Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,"Mod"`) + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms", `'Member','{"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'`) + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_banned", `'Banned','{"ViewTopic":true}','{}',1`) + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms", `'Awaiting Activation','{"ViewTopic":true}','{}'`) + + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, tag", `'Not Loggedin','{"ViewTopic":true}','{}','Guest'`) + + // + // TODO: Stop processFields() from stripping the spaces in the descriptions in the next commit + + qgen.Install.SimpleInsert("forums", "name, active, desc", "'Reports',0,'All the reports go here'") + + qgen.Install.SimpleInsert("forums", "name, lastTopicID, lastReplyerID, desc", "'General',1,1,'A place for general discussions which don't fit elsewhere'") + + // + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}'`) + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}'`) + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", "3,1,'{}'") + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", "4,1,'{}'") + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", "5,1,'{}'") + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", "6,1,'{}'") + + // + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `1,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'`) + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `2,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'`) + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `3,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true}'`) + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `4,2,'{"ViewTopic":true}'`) + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `5,2,'{"ViewTopic":true}'`) + + qgen.Install.SimpleInsert("forums_permissions", "gid, fid, permissions", `6,2,'{"ViewTopic":true}'`) + + // + + qgen.Install.SimpleInsert("topics", "title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, createdBy, parentID", "'Test Topic','A topic automatically generated by the software.','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2") + + qgen.Install.SimpleInsert("replies", "tid, content, parsed_content, createdAt, createdBy, lastUpdated, lastEdit, lastEditBy", "1,'A reply!','A reply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0") + return nil } @@ -276,7 +631,7 @@ func write_selects(adapter qgen.DB_Adapter) error { // nolint func write_left_joins(adapter qgen.DB_Adapter) error { - adapter.SimpleLeftJoin("getTopicRepliesOffset", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "tid = ?", "", "?,?") + adapter.SimpleLeftJoin("getTopicRepliesOffset", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "", "?,?") adapter.SimpleLeftJoin("getTopicList", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", "") @@ -302,25 +657,25 @@ func write_inner_joins(adapter qgen.DB_Adapter) error { // nolint func write_inserts(adapter qgen.DB_Adapter) error { - adapter.SimpleInsert("createTopic", "topics", "parentID,title,content,parsed_content,createdAt,lastReplyAt,lastReplyBy,ipaddress,words,createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?") + adapter.SimpleInsert("createTopic", "topics", "parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?") - adapter.SimpleInsert("createReport", "topics", "title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report'") + adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report'") - adapter.SimpleInsert("createReply", "replies", "tid,content,parsed_content,createdAt,ipaddress,words,createdBy", "?,?,?,UTC_TIMESTAMP(),?,?,?") + adapter.SimpleInsert("createReply", "replies", "tid, content, parsed_content, createdAt, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),?,?,?") - adapter.SimpleInsert("createActionReply", "replies", "tid,actionType,ipaddress,createdBy", "?,?,?,?") + adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy", "?,?,?,?") adapter.SimpleInsert("createLike", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?") - adapter.SimpleInsert("addActivity", "activity_stream", "actor,targetUser,event,elementType,elementID", "?,?,?,?,?") + adapter.SimpleInsert("addActivity", "activity_stream", "actor, targetUser, event, elementType, elementID", "?,?,?,?,?") - adapter.SimpleInsert("notifyOne", "activity_stream_matches", "watcher,asid", "?,?") + adapter.SimpleInsert("notifyOne", "activity_stream_matches", "watcher, asid", "?,?") adapter.SimpleInsert("addEmail", "emails", "email, uid, validated, token", "?,?,?,?") adapter.SimpleInsert("createProfileReply", "users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?") - adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user,targetID,targetType,level", "?,?,?,2") + adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user, targetID, targetType, level", "?,?,?,2") adapter.SimpleInsert("createForum", "forums", "name, desc, active, preset", "?,?,?,?") @@ -328,7 +683,7 @@ func write_inserts(adapter qgen.DB_Adapter) error { adapter.SimpleInsert("addPlugin", "plugins", "uname, active, installed", "?,?,?") - adapter.SimpleInsert("addTheme", "themes", "uname,default", "?,?") + adapter.SimpleInsert("addTheme", "themes", "uname, default", "?,?") adapter.SimpleInsert("createGroup", "users_groups", "name, tag, is_admin, is_mod, is_banned, permissions", "?,?,?,?,?,?") @@ -345,7 +700,7 @@ func write_inserts(adapter qgen.DB_Adapter) error { // nolint func write_replaces(adapter qgen.DB_Adapter) error { - adapter.SimpleReplace("addForumPermsToGroup", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") + adapter.SimpleReplace("addForumPermsToGroup", "forums_permissions", "gid, fid, preset, permissions", "?,?,?,?") adapter.SimpleReplace("replaceScheduleGroup", "users_groups_scheduler", "uid, set_group, issued_by, issued_at, revert_at, temporary", "?,?,?,UTC_TIMESTAMP(),?,?") @@ -469,17 +824,17 @@ func write_simple_counts(adapter qgen.DB_Adapter) error { // nolint func write_insert_selects(adapter qgen.DB_Adapter) error { adapter.SimpleInsertSelect("addForumPermsToForumAdmins", - qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""}, ) adapter.SimpleInsertSelect("addForumPermsToForumStaff", - qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""}, ) adapter.SimpleInsertSelect("addForumPermsToForumMembers", - qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""}, ) diff --git a/routes.go b/routes.go index 05a04c7f..2419724b 100644 --- a/routes.go +++ b/routes.go @@ -235,14 +235,11 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user User) { //topicItem.ForumLink = "" } - /*topicItem.CreatedAt, err = relativeTime(topicItem.CreatedAt) + /*topicItem.CreatedAt, err = relativeTimeFromString(topicItem.CreatedAt) if err != nil { replyItem.CreatedAt = "" }*/ - topicItem.LastReplyAt, err = relativeTime(topicItem.LastReplyAt) - if err != nil { - InternalError(err, w) - } + topicItem.RelativeLastReplyAt = relativeTime(topicItem.LastReplyAt) if vhooks["topics_topic_row_assign"] != nil { runVhook("topics_topic_row_assign", &topicItem, &forum) @@ -354,10 +351,7 @@ func routeForum(w http.ResponseWriter, r *http.Request, user User, sfid string) } topicItem.Link = buildTopicURL(nameToSlug(topicItem.Title), topicItem.ID) - topicItem.LastReplyAt, err = relativeTime(topicItem.LastReplyAt) - if err != nil { - InternalError(err, w) - } + topicItem.RelativeLastReplyAt = relativeTime(topicItem.LastReplyAt) if vhooks["forum_trow_assign"] != nil { runVhook("forum_trow_assign", &topicItem, &forum) @@ -439,7 +433,7 @@ func routeForums(w http.ResponseWriter, r *http.Request, user User) { //topic, user := forum.GetLast() //if topic.ID != 0 && user.ID != 0 { if forum.LastTopic.ID != 0 && forum.LastReplyer.ID != 0 { - forum.LastTopicTime, err = relativeTime(forum.LastTopic.LastReplyAt) + forum.LastTopicTime, err = relativeTimeFromString(forum.LastTopic.LastReplyAt) if err != nil { InternalError(err, w) return @@ -539,7 +533,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) { } }*/ - topic.CreatedAt, err = relativeTime(topic.CreatedAt) + topic.CreatedAt, err = relativeTimeFromString(topic.CreatedAt) if err != nil { topic.CreatedAt = "" } @@ -624,7 +618,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) { } }*/ - replyItem.CreatedAt, err = relativeTime(replyItem.CreatedAt) + replyItem.CreatedAt, err = relativeTimeFromString(replyItem.CreatedAt) if err != nil { replyItem.CreatedAt = "" } diff --git a/run_mssql.bat b/run_mssql.bat new file mode 100644 index 00000000..ed968f07 --- /dev/null +++ b/run_mssql.bat @@ -0,0 +1,36 @@ +@echo off +echo Generating the dynamic code +go generate +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + +echo Building the router generator +go build ./router_gen +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) +echo Running the router generator +router_gen.exe + +echo Building the query generator +go build ./query_gen +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) +echo Running the query generator +query_gen.exe + +echo Building the executable +go build -o gosora.exe -tags mssql +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + +echo Running Gosora +gosora.exe +pause \ No newline at end of file diff --git a/schema/mssql/inserts.sql b/schema/mssql/inserts.sql new file mode 100644 index 00000000..e37b4b62 --- /dev/null +++ b/schema/mssql/inserts.sql @@ -0,0 +1,29 @@ +INSERT INTO [sync] ([last_update]) VALUES (GETUTCDATE()); +INSERT INTO [settings] ([name],[content],[type]) VALUES ('url_tags','1','bool'); +INSERT INTO [settings] ([name],[content],[type],[constraints]) VALUES ('activation_type','1','list','1-3'); +INSERT INTO [settings] ([name],[content],[type]) VALUES ('bigpost_min_words','250','int'); +INSERT INTO [settings] ([name],[content],[type]) VALUES ('megapost_min_words','1000','int'); +INSERT INTO [themes] ([uname],[default]) VALUES ('tempra-simple',1); +INSERT INTO [emails] ([email],[uid],[validated]) VALUES ('admin@localhost',1,1); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,1,'Admin'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,'Mod'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms]) VALUES ('Member','{"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_banned]) VALUES ('Banned','{"ViewTopic":true}','{}',1); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms]) VALUES ('AwaitingActivation','{"ViewTopic":true}','{}'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[tag]) VALUES ('NotLoggedin','{"ViewTopic":true}','{}','Guest'); +INSERT INTO [forums] ([name],[active],[desc]) VALUES ('Reports',0,'Allthereportsgohere'); +INSERT INTO [forums] ([name],[lastTopicID],[lastReplyerID],[desc]) VALUES ('General',1,1,'Aplaceforgeneraldiscussionswhichdon''tfitelsewhere'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (3,1,'{}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (4,1,'{}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (5,1,'{}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (6,1,'{}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (1,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (2,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (3,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (4,2,'{"ViewTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (5,2,'{"ViewTopic":true}'); +INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (6,2,'{"ViewTopic":true}'); +INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[createdBy],[parentID]) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',GETUTCDATE(),GETUTCDATE(),1,1,2); +INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[createdBy],[lastUpdated],[lastEdit],[lastEditBy]) VALUES (1,'Areply!','Areply!',GETUTCDATE(),1,GETUTCDATE(),0,0); diff --git a/schema/mssql/query_activity_stream.sql b/schema/mssql/query_activity_stream.sql new file mode 100644 index 00000000..b61301e4 --- /dev/null +++ b/schema/mssql/query_activity_stream.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS [activity_stream]; +CREATE TABLE [activity_stream] ( + [asid] int not null IDENTITY, + [actor] int not null, + [targetUser] int not null, + [event] nvarchar (50) not null, + [elementType] nvarchar (50) not null, + [elementID] int not null, + primary key([asid]) +); \ No newline at end of file diff --git a/schema/mssql/query_activity_stream_matches.sql b/schema/mssql/query_activity_stream_matches.sql new file mode 100644 index 00000000..73821dc5 --- /dev/null +++ b/schema/mssql/query_activity_stream_matches.sql @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS [activity_stream_matches]; +CREATE TABLE [activity_stream_matches] ( + [watcher] int not null, + [asid] int not null +); \ No newline at end of file diff --git a/schema/mssql/query_activity_subscriptions.sql b/schema/mssql/query_activity_subscriptions.sql new file mode 100644 index 00000000..6c0a2df8 --- /dev/null +++ b/schema/mssql/query_activity_subscriptions.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS [activity_subscriptions]; +CREATE TABLE [activity_subscriptions] ( + [user] int not null, + [targetID] int not null, + [targetType] nvarchar (50) not null, + [level] int DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/mssql/query_administration_logs.sql b/schema/mssql/query_administration_logs.sql new file mode 100644 index 00000000..40c398e1 --- /dev/null +++ b/schema/mssql/query_administration_logs.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS [administration_logs]; +CREATE TABLE [administration_logs] ( + [action] nvarchar (100) not null, + [elementID] int not null, + [elementType] nvarchar (100) not null, + [ipaddress] nvarchar (200) not null, + [actorID] int not null, + [doneAt] datetime not null +); \ No newline at end of file diff --git a/schema/mssql/query_attachments.sql b/schema/mssql/query_attachments.sql new file mode 100644 index 00000000..cadd3337 --- /dev/null +++ b/schema/mssql/query_attachments.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS [attachments]; +CREATE TABLE [attachments] ( + [attachID] int not null IDENTITY, + [sectionID] int DEFAULT 0 not null, + [sectionTable] nvarchar (200) DEFAULT 'forums' not null, + [originID] int not null, + [originTable] nvarchar (200) DEFAULT 'replies' not null, + [uploadedBy] int not null, + [path] nvarchar (200) not null, + primary key([attachID]) +); \ No newline at end of file diff --git a/schema/mssql/query_emails.sql b/schema/mssql/query_emails.sql new file mode 100644 index 00000000..a04ed884 --- /dev/null +++ b/schema/mssql/query_emails.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS [emails]; +CREATE TABLE [emails] ( + [email] nvarchar (200) not null, + [uid] int not null, + [validated] bit DEFAULT 0 not null, + [token] nvarchar (200) DEFAULT '' not null +); \ No newline at end of file diff --git a/schema/mssql/query_forums.sql b/schema/mssql/query_forums.sql new file mode 100644 index 00000000..4d31b9de --- /dev/null +++ b/schema/mssql/query_forums.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS [forums]; +CREATE TABLE [forums] ( + [fid] int not null IDENTITY, + [name] nvarchar (100) not null, + [desc] nvarchar (200) not null, + [active] bit DEFAULT 1 not null, + [topicCount] int DEFAULT 0 not null, + [preset] nvarchar (100) DEFAULT '' not null, + [parentID] int DEFAULT 0 not null, + [parentType] nvarchar (50) DEFAULT '' not null, + [lastTopicID] int DEFAULT 0 not null, + [lastReplyerID] int DEFAULT 0 not null, + primary key([fid]) +); \ No newline at end of file diff --git a/schema/mssql/query_forums_permissions.sql b/schema/mssql/query_forums_permissions.sql new file mode 100644 index 00000000..d0025818 --- /dev/null +++ b/schema/mssql/query_forums_permissions.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS [forums_permissions]; +CREATE TABLE [forums_permissions] ( + [fid] int not null, + [gid] int not null, + [preset] nvarchar (100) DEFAULT '' not null, + [permissions] nvarchar (MAX) not null, + primary key([fid],[gid]) +); \ No newline at end of file diff --git a/schema/mssql/query_likes.sql b/schema/mssql/query_likes.sql new file mode 100644 index 00000000..d56977b8 --- /dev/null +++ b/schema/mssql/query_likes.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS [likes]; +CREATE TABLE [likes] ( + [weight] tinyint DEFAULT 1 not null, + [targetItem] int not null, + [targetType] nvarchar (50) DEFAULT 'replies' not null, + [sentBy] int not null, + [recalc] tinyint DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/mssql/query_moderation_logs.sql b/schema/mssql/query_moderation_logs.sql new file mode 100644 index 00000000..4e64a148 --- /dev/null +++ b/schema/mssql/query_moderation_logs.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS [moderation_logs]; +CREATE TABLE [moderation_logs] ( + [action] nvarchar (100) not null, + [elementID] int not null, + [elementType] nvarchar (100) not null, + [ipaddress] nvarchar (200) not null, + [actorID] int not null, + [doneAt] datetime not null +); \ No newline at end of file diff --git a/schema/mssql/query_plugins.sql b/schema/mssql/query_plugins.sql new file mode 100644 index 00000000..64c84660 --- /dev/null +++ b/schema/mssql/query_plugins.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS [plugins]; +CREATE TABLE [plugins] ( + [uname] nvarchar (180) not null, + [active] bit DEFAULT 0 not null, + [installed] bit DEFAULT 0 not null, + unique([uname]) +); \ No newline at end of file diff --git a/schema/mssql/query_replies.sql b/schema/mssql/query_replies.sql new file mode 100644 index 00000000..745231de --- /dev/null +++ b/schema/mssql/query_replies.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS [replies]; +CREATE TABLE [replies] ( + [rid] int not null IDENTITY, + [tid] int not null, + [content] nvarchar (MAX) not null, + [parsed_content] nvarchar (MAX) not null, + [createdAt] datetime not null, + [createdBy] int not null, + [lastEdit] int not null, + [lastEditBy] int not null, + [lastUpdated] datetime not null, + [ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null, + [likeCount] int DEFAULT 0 not null, + [words] int DEFAULT 1 not null, + [actionType] nvarchar (20) DEFAULT '' not null, + primary key([rid]) +); \ No newline at end of file diff --git a/schema/mssql/query_revisions.sql b/schema/mssql/query_revisions.sql new file mode 100644 index 00000000..66cb16de --- /dev/null +++ b/schema/mssql/query_revisions.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS [revisions]; +CREATE TABLE [revisions] ( + [index] int not null, + [content] nvarchar (MAX) not null, + [contentID] int not null, + [contentType] nvarchar (100) DEFAULT 'replies' not null +); \ No newline at end of file diff --git a/schema/mssql/query_settings.sql b/schema/mssql/query_settings.sql new file mode 100644 index 00000000..fee55368 --- /dev/null +++ b/schema/mssql/query_settings.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS [settings]; +CREATE TABLE [settings] ( + [name] nvarchar (180) not null, + [content] nvarchar (250) not null, + [type] nvarchar (50) not null, + [constraints] nvarchar (200) DEFAULT '' not null, + unique([name]) +); \ No newline at end of file diff --git a/schema/mssql/query_sync.sql b/schema/mssql/query_sync.sql new file mode 100644 index 00000000..a540f503 --- /dev/null +++ b/schema/mssql/query_sync.sql @@ -0,0 +1,4 @@ +DROP TABLE IF EXISTS [sync]; +CREATE TABLE [sync] ( + [last_update] datetime not null +); \ No newline at end of file diff --git a/schema/mssql/query_themes.sql b/schema/mssql/query_themes.sql new file mode 100644 index 00000000..757095b0 --- /dev/null +++ b/schema/mssql/query_themes.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS [themes]; +CREATE TABLE [themes] ( + [uname] nvarchar (180) not null, + [default] bit DEFAULT 0 not null, + unique([uname]) +); \ No newline at end of file diff --git a/schema/mssql/query_topics.sql b/schema/mssql/query_topics.sql new file mode 100644 index 00000000..cd42bfac --- /dev/null +++ b/schema/mssql/query_topics.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS [topics]; +CREATE TABLE [topics] ( + [tid] int not null IDENTITY, + [title] nvarchar (100) not null, + [content] nvarchar (MAX) not null, + [parsed_content] nvarchar (MAX) not null, + [createdAt] datetime not null, + [lastReplyAt] datetime not null, + [lastReplyBy] int not null, + [createdBy] int not null, + [is_closed] bit DEFAULT 0 not null, + [sticky] bit DEFAULT 0 not null, + [parentID] int DEFAULT 2 not null, + [ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null, + [postCount] int DEFAULT 1 not null, + [likeCount] int DEFAULT 0 not null, + [words] int DEFAULT 0 not null, + [css_class] nvarchar (100) DEFAULT '' not null, + [data] nvarchar (200) DEFAULT '' not null, + primary key([tid]) +); \ No newline at end of file diff --git a/schema/mssql/query_users.sql b/schema/mssql/query_users.sql new file mode 100644 index 00000000..fbfbfaf8 --- /dev/null +++ b/schema/mssql/query_users.sql @@ -0,0 +1,28 @@ +DROP TABLE IF EXISTS [users]; +CREATE TABLE [users] ( + [uid] int not null IDENTITY, + [name] nvarchar (100) not null, + [password] nvarchar (100) not null, + [salt] nvarchar (80) DEFAULT '' not null, + [group] int not null, + [active] bit DEFAULT 0 not null, + [is_super_admin] bit DEFAULT 0 not null, + [createdAt] datetime not null, + [lastActiveAt] datetime not null, + [session] nvarchar (200) DEFAULT '' not null, + [last_ip] nvarchar (200) DEFAULT '0.0.0.0.0' not null, + [email] nvarchar (200) DEFAULT '' not null, + [avatar] nvarchar (100) DEFAULT '' not null, + [message] nvarchar (MAX) DEFAULT '' not null, + [url_prefix] nvarchar (20) DEFAULT '' not null, + [url_name] nvarchar (100) DEFAULT '' not null, + [level] smallint DEFAULT 0 not null, + [score] int DEFAULT 0 not null, + [posts] int DEFAULT 0 not null, + [bigposts] int DEFAULT 0 not null, + [megaposts] int DEFAULT 0 not null, + [topics] int DEFAULT 0 not null, + [temp_group] int DEFAULT 0 not null, + primary key([uid]), + unique([name]) +); \ No newline at end of file diff --git a/schema/mssql/query_users_groups.sql b/schema/mssql/query_users_groups.sql new file mode 100644 index 00000000..867decda --- /dev/null +++ b/schema/mssql/query_users_groups.sql @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS [users_groups]; +CREATE TABLE [users_groups] ( + [gid] int not null IDENTITY, + [name] nvarchar (100) not null, + [permissions] nvarchar (MAX) not null, + [plugin_perms] nvarchar (MAX) not null, + [is_mod] bit DEFAULT 0 not null, + [is_admin] bit DEFAULT 0 not null, + [is_banned] bit DEFAULT 0 not null, + [tag] nvarchar (50) DEFAULT '' not null, + primary key([gid]) +); \ No newline at end of file diff --git a/schema/mssql/query_users_groups_scheduler.sql b/schema/mssql/query_users_groups_scheduler.sql new file mode 100644 index 00000000..7869365e --- /dev/null +++ b/schema/mssql/query_users_groups_scheduler.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS [users_groups_scheduler]; +CREATE TABLE [users_groups_scheduler] ( + [uid] int not null, + [set_group] int not null, + [issued_by] int not null, + [issued_at] datetime not null, + [revert_at] datetime not null, + [temporary] bit not null, + primary key([uid]) +); \ No newline at end of file diff --git a/schema/mssql/query_users_replies.sql b/schema/mssql/query_users_replies.sql new file mode 100644 index 00000000..f4a24d91 --- /dev/null +++ b/schema/mssql/query_users_replies.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS [users_replies]; +CREATE TABLE [users_replies] ( + [rid] int not null IDENTITY, + [uid] int not null, + [content] nvarchar (MAX) not null, + [parsed_content] nvarchar (MAX) not null, + [createdAt] datetime not null, + [createdBy] int not null, + [lastEdit] int not null, + [lastEditBy] int not null, + [ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null, + primary key([rid]) +); \ No newline at end of file diff --git a/schema/mssql/query_widgets.sql b/schema/mssql/query_widgets.sql new file mode 100644 index 00000000..1cb52246 --- /dev/null +++ b/schema/mssql/query_widgets.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS [widgets]; +CREATE TABLE [widgets] ( + [position] int not null, + [side] nvarchar (100) not null, + [type] nvarchar (100) not null, + [active] bit DEFAULT 0 not null, + [location] nvarchar (100) not null, + [data] nvarchar (MAX) DEFAULT '' not null +); \ No newline at end of file diff --git a/schema/mssql/query_word_filters.sql b/schema/mssql/query_word_filters.sql new file mode 100644 index 00000000..036c405a --- /dev/null +++ b/schema/mssql/query_word_filters.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS [word_filters]; +CREATE TABLE [word_filters] ( + [wfid] int not null IDENTITY, + [find] nvarchar (200) not null, + [replacement] nvarchar (200) not null, + primary key([wfid]) +); \ No newline at end of file diff --git a/schema/mysql/inserts.sql b/schema/mysql/inserts.sql index e69de29b..a588d2c3 100644 --- a/schema/mysql/inserts.sql +++ b/schema/mysql/inserts.sql @@ -0,0 +1,29 @@ +INSERT INTO `sync`(`last_update`) VALUES (UTC_TIMESTAMP()); +INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('url_tags','1','bool'); +INSERT INTO `settings`(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3'); +INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('bigpost_min_words','250','int'); +INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('megapost_min_words','1000','int'); +INSERT INTO `themes`(`uname`,`default`) VALUES ('tempra-simple',1); +INSERT INTO `emails`(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,1,'Admin'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}','{}',1,'Mod'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`) VALUES ('Member','{"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_banned`) VALUES ('Banned','{"ViewTopic":true}','{}',1); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`) VALUES ('AwaitingActivation','{"ViewTopic":true}','{}'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('NotLoggedin','{"ViewTopic":true}','{}','Guest'); +INSERT INTO `forums`(`name`,`active`,`desc`) VALUES ('Reports',0,'Allthereportsgohere'); +INSERT INTO `forums`(`name`,`lastTopicID`,`lastReplyerID`,`desc`) VALUES ('General',1,1,'Aplaceforgeneraldiscussionswhichdon''tfitelsewhere'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (3,1,'{}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (4,1,'{}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (5,1,'{}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (6,1,'{}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (1,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (2,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true,"EditTopic":true,"DeleteTopic":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (3,2,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"LikeItem":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (4,2,'{"ViewTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (5,2,'{"ViewTopic":true}'); +INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (6,2,'{"ViewTopic":true}'); +INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`createdBy`,`parentID`) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2); +INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`lastUpdated`,`lastEdit`,`lastEditBy`) VALUES (1,'Areply!','Areply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0); diff --git a/schema/mysql/query_activity_stream.sql b/schema/mysql/query_activity_stream.sql new file mode 100644 index 00000000..07883079 --- /dev/null +++ b/schema/mysql/query_activity_stream.sql @@ -0,0 +1,9 @@ +CREATE TABLE `activity_stream` ( + `asid` int not null AUTO_INCREMENT, + `actor` int not null, + `targetUser` int not null, + `event` varchar(50) not null, + `elementType` varchar(50) not null, + `elementID` int not null, + primary key(`asid`) +); \ No newline at end of file diff --git a/schema/mysql/query_activity_stream_matches.sql b/schema/mysql/query_activity_stream_matches.sql new file mode 100644 index 00000000..d4139a9b --- /dev/null +++ b/schema/mysql/query_activity_stream_matches.sql @@ -0,0 +1,4 @@ +CREATE TABLE `activity_stream_matches` ( + `watcher` int not null, + `asid` int not null +); \ No newline at end of file diff --git a/schema/mysql/query_activity_subscriptions.sql b/schema/mysql/query_activity_subscriptions.sql new file mode 100644 index 00000000..e3140676 --- /dev/null +++ b/schema/mysql/query_activity_subscriptions.sql @@ -0,0 +1,6 @@ +CREATE TABLE `activity_subscriptions` ( + `user` int not null, + `targetID` int not null, + `targetType` varchar(50) not null, + `level` int DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/mysql/query_administration_logs.sql b/schema/mysql/query_administration_logs.sql new file mode 100644 index 00000000..eb4c3cd1 --- /dev/null +++ b/schema/mysql/query_administration_logs.sql @@ -0,0 +1,8 @@ +CREATE TABLE `administration_logs` ( + `action` varchar(100) not null, + `elementID` int not null, + `elementType` varchar(100) not null, + `ipaddress` varchar(200) not null, + `actorID` int not null, + `doneAt` datetime not null +); \ No newline at end of file diff --git a/schema/mysql/query_attachments.sql b/schema/mysql/query_attachments.sql new file mode 100644 index 00000000..6f297d8e --- /dev/null +++ b/schema/mysql/query_attachments.sql @@ -0,0 +1,10 @@ +CREATE TABLE `attachments` ( + `attachID` int not null AUTO_INCREMENT, + `sectionID` int DEFAULT 0 not null, + `sectionTable` varchar(200) DEFAULT 'forums' not null, + `originID` int not null, + `originTable` varchar(200) DEFAULT 'replies' not null, + `uploadedBy` int not null, + `path` varchar(200) not null, + primary key(`attachID`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_emails.sql b/schema/mysql/query_emails.sql new file mode 100644 index 00000000..bf46887f --- /dev/null +++ b/schema/mysql/query_emails.sql @@ -0,0 +1,6 @@ +CREATE TABLE `emails` ( + `email` varchar(200) not null, + `uid` int not null, + `validated` boolean DEFAULT 0 not null, + `token` varchar(200) DEFAULT '' not null +); \ No newline at end of file diff --git a/schema/mysql/query_forums.sql b/schema/mysql/query_forums.sql new file mode 100644 index 00000000..848f42a1 --- /dev/null +++ b/schema/mysql/query_forums.sql @@ -0,0 +1,13 @@ +CREATE TABLE `forums` ( + `fid` int not null AUTO_INCREMENT, + `name` varchar(100) not null, + `desc` varchar(200) not null, + `active` boolean DEFAULT 1 not null, + `topicCount` int DEFAULT 0 not null, + `preset` varchar(100) DEFAULT '' not null, + `parentID` int DEFAULT 0 not null, + `parentType` varchar(50) DEFAULT '' not null, + `lastTopicID` int DEFAULT 0 not null, + `lastReplyerID` int DEFAULT 0 not null, + primary key(`fid`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_forums_permissions.sql b/schema/mysql/query_forums_permissions.sql new file mode 100644 index 00000000..41d39a83 --- /dev/null +++ b/schema/mysql/query_forums_permissions.sql @@ -0,0 +1,7 @@ +CREATE TABLE `forums_permissions` ( + `fid` int not null, + `gid` int not null, + `preset` varchar(100) DEFAULT '' not null, + `permissions` text not null, + primary key(`fid`,`gid`) +); \ No newline at end of file diff --git a/schema/mysql/query_likes.sql b/schema/mysql/query_likes.sql new file mode 100644 index 00000000..b73b8cf0 --- /dev/null +++ b/schema/mysql/query_likes.sql @@ -0,0 +1,7 @@ +CREATE TABLE `likes` ( + `weight` tinyint DEFAULT 1 not null, + `targetItem` int not null, + `targetType` varchar(50) DEFAULT 'replies' not null, + `sentBy` int not null, + `recalc` tinyint DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/mysql/query_moderation_logs.sql b/schema/mysql/query_moderation_logs.sql new file mode 100644 index 00000000..5eb65133 --- /dev/null +++ b/schema/mysql/query_moderation_logs.sql @@ -0,0 +1,8 @@ +CREATE TABLE `moderation_logs` ( + `action` varchar(100) not null, + `elementID` int not null, + `elementType` varchar(100) not null, + `ipaddress` varchar(200) not null, + `actorID` int not null, + `doneAt` datetime not null +); \ No newline at end of file diff --git a/schema/mysql/query_plugins.sql b/schema/mysql/query_plugins.sql new file mode 100644 index 00000000..a8134f2d --- /dev/null +++ b/schema/mysql/query_plugins.sql @@ -0,0 +1,6 @@ +CREATE TABLE `plugins` ( + `uname` varchar(180) not null, + `active` boolean DEFAULT 0 not null, + `installed` boolean DEFAULT 0 not null, + unique(`uname`) +); \ No newline at end of file diff --git a/schema/mysql/query_replies.sql b/schema/mysql/query_replies.sql new file mode 100644 index 00000000..ce1860fe --- /dev/null +++ b/schema/mysql/query_replies.sql @@ -0,0 +1,16 @@ +CREATE TABLE `replies` ( + `rid` int not null AUTO_INCREMENT, + `tid` int not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` datetime not null, + `createdBy` int not null, + `lastEdit` int not null, + `lastEditBy` int not null, + `lastUpdated` datetime not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, + `likeCount` int DEFAULT 0 not null, + `words` int DEFAULT 1 not null, + `actionType` varchar(20) DEFAULT '' not null, + primary key(`rid`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_revisions.sql b/schema/mysql/query_revisions.sql new file mode 100644 index 00000000..61cb705e --- /dev/null +++ b/schema/mysql/query_revisions.sql @@ -0,0 +1,6 @@ +CREATE TABLE `revisions` ( + `index` int not null, + `content` text not null, + `contentID` int not null, + `contentType` varchar(100) DEFAULT 'replies' not null +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_settings.sql b/schema/mysql/query_settings.sql new file mode 100644 index 00000000..0e931e69 --- /dev/null +++ b/schema/mysql/query_settings.sql @@ -0,0 +1,7 @@ +CREATE TABLE `settings` ( + `name` varchar(180) not null, + `content` varchar(250) not null, + `type` varchar(50) not null, + `constraints` varchar(200) DEFAULT '' not null, + unique(`name`) +); \ No newline at end of file diff --git a/schema/mysql/query_themes.sql b/schema/mysql/query_themes.sql new file mode 100644 index 00000000..a84a3cdd --- /dev/null +++ b/schema/mysql/query_themes.sql @@ -0,0 +1,5 @@ +CREATE TABLE `themes` ( + `uname` varchar(180) not null, + `default` boolean DEFAULT 0 not null, + unique(`uname`) +); \ No newline at end of file diff --git a/schema/mysql/query_topics.sql b/schema/mysql/query_topics.sql new file mode 100644 index 00000000..6475add6 --- /dev/null +++ b/schema/mysql/query_topics.sql @@ -0,0 +1,20 @@ +CREATE TABLE `topics` ( + `tid` int not null AUTO_INCREMENT, + `title` varchar(100) not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` datetime not null, + `lastReplyAt` datetime not null, + `lastReplyBy` int not null, + `createdBy` int not null, + `is_closed` boolean DEFAULT 0 not null, + `sticky` boolean DEFAULT 0 not null, + `parentID` int DEFAULT 2 not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, + `postCount` int DEFAULT 1 not null, + `likeCount` int DEFAULT 0 not null, + `words` int DEFAULT 0 not null, + `css_class` varchar(100) DEFAULT '' not null, + `data` varchar(200) DEFAULT '' not null, + primary key(`tid`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_users_groups.sql b/schema/mysql/query_users_groups.sql new file mode 100644 index 00000000..ccdf0085 --- /dev/null +++ b/schema/mysql/query_users_groups.sql @@ -0,0 +1,11 @@ +CREATE TABLE `users_groups` ( + `gid` int not null AUTO_INCREMENT, + `name` varchar(100) not null, + `permissions` text not null, + `plugin_perms` text not null, + `is_mod` boolean DEFAULT 0 not null, + `is_admin` boolean DEFAULT 0 not null, + `is_banned` boolean DEFAULT 0 not null, + `tag` varchar(50) DEFAULT '' not null, + primary key(`gid`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_users_replies.sql b/schema/mysql/query_users_replies.sql new file mode 100644 index 00000000..b25499de --- /dev/null +++ b/schema/mysql/query_users_replies.sql @@ -0,0 +1,12 @@ +CREATE TABLE `users_replies` ( + `rid` int not null AUTO_INCREMENT, + `uid` int not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` datetime not null, + `createdBy` int not null, + `lastEdit` int not null, + `lastEditBy` int not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, + primary key(`rid`) +) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; \ No newline at end of file diff --git a/schema/mysql/query_widgets.sql b/schema/mysql/query_widgets.sql new file mode 100644 index 00000000..e2d1e980 --- /dev/null +++ b/schema/mysql/query_widgets.sql @@ -0,0 +1,8 @@ +CREATE TABLE `widgets` ( + `position` int not null, + `side` varchar(100) not null, + `type` varchar(100) not null, + `active` boolean DEFAULT 0 not null, + `location` varchar(100) not null, + `data` text not null +); \ No newline at end of file diff --git a/schema/pgsql/inserts.sql b/schema/pgsql/inserts.sql index e69de29b..136d3909 100644 --- a/schema/pgsql/inserts.sql +++ b/schema/pgsql/inserts.sql @@ -0,0 +1,29 @@ +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; diff --git a/schema/pgsql/query_activity_stream.sql b/schema/pgsql/query_activity_stream.sql new file mode 100644 index 00000000..ddbeaaa7 --- /dev/null +++ b/schema/pgsql/query_activity_stream.sql @@ -0,0 +1,9 @@ +CREATE TABLE `activity_stream` ( + `asid` serial not null, + `actor` int not null, + `targetUser` int not null, + `event` varchar (50) not null, + `elementType` varchar (50) not null, + `elementID` int not null, + primary key(`asid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_activity_stream_matches.sql b/schema/pgsql/query_activity_stream_matches.sql new file mode 100644 index 00000000..d4139a9b --- /dev/null +++ b/schema/pgsql/query_activity_stream_matches.sql @@ -0,0 +1,4 @@ +CREATE TABLE `activity_stream_matches` ( + `watcher` int not null, + `asid` int not null +); \ No newline at end of file diff --git a/schema/pgsql/query_activity_subscriptions.sql b/schema/pgsql/query_activity_subscriptions.sql new file mode 100644 index 00000000..9ae31495 --- /dev/null +++ b/schema/pgsql/query_activity_subscriptions.sql @@ -0,0 +1,6 @@ +CREATE TABLE `activity_subscriptions` ( + `user` int not null, + `targetID` int not null, + `targetType` varchar (50) not null, + `level` int DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/pgsql/query_administration_logs.sql b/schema/pgsql/query_administration_logs.sql new file mode 100644 index 00000000..73f59cf6 --- /dev/null +++ b/schema/pgsql/query_administration_logs.sql @@ -0,0 +1,8 @@ +CREATE TABLE `administration_logs` ( + `action` varchar (100) not null, + `elementID` int not null, + `elementType` varchar (100) not null, + `ipaddress` varchar (200) not null, + `actorID` int not null, + `doneAt` timestamp not null +); \ No newline at end of file diff --git a/schema/pgsql/query_attachments.sql b/schema/pgsql/query_attachments.sql new file mode 100644 index 00000000..11ec6798 --- /dev/null +++ b/schema/pgsql/query_attachments.sql @@ -0,0 +1,10 @@ +CREATE TABLE `attachments` ( + `attachID` serial not null, + `sectionID` int DEFAULT 0 not null, + `sectionTable` varchar (200) DEFAULT 'forums' not null, + `originID` int not null, + `originTable` varchar (200) DEFAULT 'replies' not null, + `uploadedBy` int not null, + `path` varchar (200) not null, + primary key(`attachID`) +); \ No newline at end of file diff --git a/schema/pgsql/query_emails.sql b/schema/pgsql/query_emails.sql new file mode 100644 index 00000000..85ff2f7c --- /dev/null +++ b/schema/pgsql/query_emails.sql @@ -0,0 +1,6 @@ +CREATE TABLE `emails` ( + `email` varchar (200) not null, + `uid` int not null, + `validated` boolean DEFAULT 0 not null, + `token` varchar (200) DEFAULT '' not null +); \ No newline at end of file diff --git a/schema/pgsql/query_forums.sql b/schema/pgsql/query_forums.sql new file mode 100644 index 00000000..081c2be8 --- /dev/null +++ b/schema/pgsql/query_forums.sql @@ -0,0 +1,13 @@ +CREATE TABLE `forums` ( + `fid` serial not null, + `name` varchar (100) not null, + `desc` varchar (200) not null, + `active` boolean DEFAULT 1 not null, + `topicCount` int DEFAULT 0 not null, + `preset` varchar (100) DEFAULT '' not null, + `parentID` int DEFAULT 0 not null, + `parentType` varchar (50) DEFAULT '' not null, + `lastTopicID` int DEFAULT 0 not null, + `lastReplyerID` int DEFAULT 0 not null, + primary key(`fid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_forums_permissions.sql b/schema/pgsql/query_forums_permissions.sql new file mode 100644 index 00000000..d5f41a4c --- /dev/null +++ b/schema/pgsql/query_forums_permissions.sql @@ -0,0 +1,7 @@ +CREATE TABLE `forums_permissions` ( + `fid` int not null, + `gid` int not null, + `preset` varchar (100) DEFAULT '' not null, + `permissions` text not null, + primary key(`fid`,`gid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_likes.sql b/schema/pgsql/query_likes.sql new file mode 100644 index 00000000..cf55c434 --- /dev/null +++ b/schema/pgsql/query_likes.sql @@ -0,0 +1,7 @@ +CREATE TABLE `likes` ( + `weight` tinyint DEFAULT 1 not null, + `targetItem` int not null, + `targetType` varchar (50) DEFAULT 'replies' not null, + `sentBy` int not null, + `recalc` tinyint DEFAULT 0 not null +); \ No newline at end of file diff --git a/schema/pgsql/query_moderation_logs.sql b/schema/pgsql/query_moderation_logs.sql new file mode 100644 index 00000000..b3d192b1 --- /dev/null +++ b/schema/pgsql/query_moderation_logs.sql @@ -0,0 +1,8 @@ +CREATE TABLE `moderation_logs` ( + `action` varchar (100) not null, + `elementID` int not null, + `elementType` varchar (100) not null, + `ipaddress` varchar (200) not null, + `actorID` int not null, + `doneAt` timestamp not null +); \ No newline at end of file diff --git a/schema/pgsql/query_plugins.sql b/schema/pgsql/query_plugins.sql new file mode 100644 index 00000000..a457c43f --- /dev/null +++ b/schema/pgsql/query_plugins.sql @@ -0,0 +1,6 @@ +CREATE TABLE `plugins` ( + `uname` varchar (180) not null, + `active` boolean DEFAULT 0 not null, + `installed` boolean DEFAULT 0 not null, + unique(`uname`) +); \ No newline at end of file diff --git a/schema/pgsql/query_replies.sql b/schema/pgsql/query_replies.sql new file mode 100644 index 00000000..1718336d --- /dev/null +++ b/schema/pgsql/query_replies.sql @@ -0,0 +1,16 @@ +CREATE TABLE `replies` ( + `rid` serial not null, + `tid` int not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` timestamp not null, + `createdBy` int not null, + `lastEdit` int not null, + `lastEditBy` int not null, + `lastUpdated` timestamp not null, + `ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null, + `likeCount` int DEFAULT 0 not null, + `words` int DEFAULT 1 not null, + `actionType` varchar (20) DEFAULT '' not null, + primary key(`rid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_revisions.sql b/schema/pgsql/query_revisions.sql new file mode 100644 index 00000000..55a9a107 --- /dev/null +++ b/schema/pgsql/query_revisions.sql @@ -0,0 +1,6 @@ +CREATE TABLE `revisions` ( + `index` int not null, + `content` text not null, + `contentID` int not null, + `contentType` varchar (100) DEFAULT 'replies' not null +); \ No newline at end of file diff --git a/schema/pgsql/query_settings.sql b/schema/pgsql/query_settings.sql new file mode 100644 index 00000000..afd0fe7e --- /dev/null +++ b/schema/pgsql/query_settings.sql @@ -0,0 +1,7 @@ +CREATE TABLE `settings` ( + `name` varchar (180) not null, + `content` varchar (250) not null, + `type` varchar (50) not null, + `constraints` varchar (200) DEFAULT '' not null, + unique(`name`) +); \ No newline at end of file diff --git a/schema/pgsql/query_themes.sql b/schema/pgsql/query_themes.sql new file mode 100644 index 00000000..6899ce85 --- /dev/null +++ b/schema/pgsql/query_themes.sql @@ -0,0 +1,5 @@ +CREATE TABLE `themes` ( + `uname` varchar (180) not null, + `default` boolean DEFAULT 0 not null, + unique(`uname`) +); \ No newline at end of file diff --git a/schema/pgsql/query_topics.sql b/schema/pgsql/query_topics.sql new file mode 100644 index 00000000..0c8d84f8 --- /dev/null +++ b/schema/pgsql/query_topics.sql @@ -0,0 +1,20 @@ +CREATE TABLE `topics` ( + `tid` serial not null, + `title` varchar (100) not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` timestamp not null, + `lastReplyAt` timestamp not null, + `lastReplyBy` int not null, + `createdBy` int not null, + `is_closed` boolean DEFAULT 0 not null, + `sticky` boolean DEFAULT 0 not null, + `parentID` int DEFAULT 2 not null, + `ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null, + `postCount` int DEFAULT 1 not null, + `likeCount` int DEFAULT 0 not null, + `words` int DEFAULT 0 not null, + `css_class` varchar (100) DEFAULT '' not null, + `data` varchar (200) DEFAULT '' not null, + primary key(`tid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_users_groups.sql b/schema/pgsql/query_users_groups.sql new file mode 100644 index 00000000..31888244 --- /dev/null +++ b/schema/pgsql/query_users_groups.sql @@ -0,0 +1,11 @@ +CREATE TABLE `users_groups` ( + `gid` serial not null, + `name` varchar (100) not null, + `permissions` text not null, + `plugin_perms` text not null, + `is_mod` boolean DEFAULT 0 not null, + `is_admin` boolean DEFAULT 0 not null, + `is_banned` boolean DEFAULT 0 not null, + `tag` varchar (50) DEFAULT '' not null, + primary key(`gid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_users_replies.sql b/schema/pgsql/query_users_replies.sql new file mode 100644 index 00000000..5ae47e19 --- /dev/null +++ b/schema/pgsql/query_users_replies.sql @@ -0,0 +1,12 @@ +CREATE TABLE `users_replies` ( + `rid` serial not null, + `uid` int not null, + `content` text not null, + `parsed_content` text not null, + `createdAt` timestamp not null, + `createdBy` int not null, + `lastEdit` int not null, + `lastEditBy` int not null, + `ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null, + primary key(`rid`) +); \ No newline at end of file diff --git a/schema/pgsql/query_widgets.sql b/schema/pgsql/query_widgets.sql new file mode 100644 index 00000000..2267e83d --- /dev/null +++ b/schema/pgsql/query_widgets.sql @@ -0,0 +1,8 @@ +CREATE TABLE `widgets` ( + `position` int not null, + `side` varchar (100) not null, + `type` varchar (100) not null, + `active` boolean DEFAULT 0 not null, + `location` varchar (100) not null, + `data` text DEFAULT '' not null +); \ No newline at end of file diff --git a/site.go b/site.go index d741eae1..aec6636e 100644 --- a/site.go +++ b/site.go @@ -24,11 +24,19 @@ type Site struct { } type DBConfig struct { + // Production database Host string Username string Password string Dbname string Port string + + // Test database. Split this into a separate variable? + TestHost string + TestUsername string + TestPassword string + TestDbname string + TestPort string } type Config struct { @@ -62,9 +70,10 @@ type DevConfig struct { SuperDebug bool TemplateDebug bool Profiling bool + TestDB bool } -func processConfig() { +func processConfig() error { config.Noavatar = strings.Replace(config.Noavatar, "{site_url}", site.URL, -1) if site.Port != "80" && site.Port != "443" { site.URL = strings.TrimSuffix(site.URL, "/") @@ -72,6 +81,14 @@ func processConfig() { site.URL = strings.TrimSuffix(site.URL, ":") site.URL = site.URL + ":" + site.Port } + // We need this in here rather than verifyConfig as switchToTestDB() currently overwrites the values it verifies + if dbConfig.TestDbname == dbConfig.Dbname { + return errors.New("Your test database can't have the same name as your production database") + } + if dev.TestDB { + switchToTestDB() + } + return nil } func verifyConfig() error { @@ -80,3 +97,11 @@ func verifyConfig() error { } return nil } + +func switchToTestDB() { + dbConfig.Host = dbConfig.TestHost + dbConfig.Username = dbConfig.TestUsername + dbConfig.Password = dbConfig.TestPassword + dbConfig.Dbname = dbConfig.TestDbname + dbConfig.Port = dbConfig.TestPort +} diff --git a/tasks.go b/tasks.go index 5cd449f9..2175a407 100644 --- a/tasks.go +++ b/tasks.go @@ -45,13 +45,7 @@ func handleExpiredScheduledGroups() error { func handleServerSync() error { var lastUpdate time.Time - var lastUpdateStr string - err := getSyncStmt.QueryRow().Scan(&lastUpdateStr) - if err != nil { - return err - } - - lastUpdate, err = time.Parse("2006-01-02 15:04:05", lastUpdateStr) + err := getSyncStmt.QueryRow().Scan(&lastUpdate) if err != nil { return err } diff --git a/template_forum.go b/template_forum.go index beb36495..a445f8be 100644 --- a/template_forum.go +++ b/template_forum.go @@ -173,7 +173,7 @@ w.Write([]byte(item.LastUser.Link)) w.Write(forum_43) w.Write([]byte(item.LastUser.Name)) w.Write(forum_44) -w.Write([]byte(item.LastReplyAt)) +w.Write([]byte(item.RelativeLastReplyAt)) w.Write(forum_45) } } else { diff --git a/template_init.go b/template_init.go index 5b536766..fef49b38 100644 --- a/template_init.go +++ b/template_init.go @@ -1,8 +1,11 @@ package main -import "log" -import "html/template" -import "net/http" +import ( + "html/template" + "log" + "net/http" + "time" +) var templates = template.New("") @@ -148,7 +151,7 @@ func compileTemplates() error { } var topicsList []*TopicsRow - topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, "Date", "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"}) + topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, "Date", time.Now(), "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"}) topicsPage := TopicsPage{"Topic List", user, headerVars, topicsList, forumList, config.DefaultForum} topicsTmpl, err := c.compileTemplate("topics.html", "templates/", "TopicsPage", topicsPage, varList) if err != nil { diff --git a/template_topics.go b/template_topics.go index c16fbb8c..129176f9 100644 --- a/template_topics.go +++ b/template_topics.go @@ -173,7 +173,7 @@ w.Write([]byte(item.LastUser.Link)) w.Write(topics_42) w.Write([]byte(item.LastUser.Name)) w.Write(topics_43) -w.Write([]byte(item.LastReplyAt)) +w.Write([]byte(item.RelativeLastReplyAt)) w.Write(topics_44) } } else { diff --git a/templates.go b/templates.go index ea7a1e5d..ae49eb26 100644 --- a/templates.go +++ b/templates.go @@ -263,8 +263,9 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value for _, key := range outVal.MapKeys() { item = outVal.MapIndex(key) } - fmt.Println("Range item:", item) - + if dev.DebugMode { + fmt.Println("Range item:", item) + } if !item.IsValid() { panic("item" + "^\n" + "Invalid map. Maybe, it doesn't have any entries for the template engine to analyse?") } diff --git a/templates/forum.html b/templates/forum.html index 5cc71f72..00ad59ff 100644 --- a/templates/forum.html +++ b/templates/forum.html @@ -62,7 +62,7 @@ {{if .LastUser.Avatar}}{{end}} {{.LastUser.Name}}
- Last: {{.LastReplyAt}} + Last: {{.RelativeLastReplyAt}} {{else}}
There aren't any topics in this forum yet.{{if .CurrentUser.Perms.CreateTopic}} Start one?{{end}}
{{end}} diff --git a/templates/topics.html b/templates/topics.html index 503ba1b4..29435139 100644 --- a/templates/topics.html +++ b/templates/topics.html @@ -62,7 +62,7 @@ {{if .LastUser.Avatar}}{{end}} {{.LastUser.Name}}
- Last: {{.LastReplyAt}} + Last: {{.RelativeLastReplyAt}}
{{else}}
There aren't any topics yet.{{if .CurrentUser.Perms.CreateTopic}} Start one?{{end}}
{{end}} diff --git a/topic.go b/topic.go index 4b1c387d..e3067b3f 100644 --- a/topic.go +++ b/topic.go @@ -11,6 +11,7 @@ import ( "html" "html/template" "strconv" + "time" ) // ? - Add a TopicMeta struct for *Forums? @@ -69,23 +70,24 @@ type TopicUser struct { } type TopicsRow struct { - ID int - Link string - Title string - Content string - CreatedBy int - IsClosed bool - Sticky bool - CreatedAt string - LastReplyAt string - LastReplyBy int - ParentID int - Status string // Deprecated. Marked for removal. -Is there anything we could use it for? - IPAddress string - PostCount int - LikeCount int - ClassName string - Data string // Used for report metadata + ID int + Link string + Title string + Content string + CreatedBy int + IsClosed bool + Sticky bool + CreatedAt string + LastReplyAt time.Time + RelativeLastReplyAt string + LastReplyBy int + ParentID int + Status string // Deprecated. Marked for removal. -Is there anything we could use it for? + IPAddress string + PostCount int + LikeCount int + ClassName string + Data string // Used for report metadata Creator *User CSS template.CSS diff --git a/update-deps-linux b/update-deps-linux index 568bc0ce..a82805cf 100644 --- a/update-deps-linux +++ b/update-deps-linux @@ -4,6 +4,9 @@ go get -u github.com/go-sql-driver/mysql echo "Updating the PostgreSQL Driver" go get -u github.com/lib/pq +echo "Updating the MSSQL Driver" +go get -u github.com/denisenkom/go-mssqldb + echo "Updating bcrypt" go get -u golang.org/x/crypto/bcrypt diff --git a/update-deps.bat b/update-deps.bat index 53257147..b73a4d8f 100644 --- a/update-deps.bat +++ b/update-deps.bat @@ -12,6 +12,13 @@ if %errorlevel% neq 0 ( exit /b %errorlevel% ) +echo Updating the MSSQL Driver +go get -u github.com/denisenkom/go-mssqldb +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + echo Updating bcrypt go get -u golang.org/x/crypto/bcrypt if %errorlevel% neq 0 ( diff --git a/utils.go b/utils.go index 8cd599cb..034ba80b 100644 --- a/utils.go +++ b/utils.go @@ -53,7 +53,7 @@ func GenerateSafeString(length int) (string, error) { } // TODO: Write a test for this -func relativeTime(in string) (string, error) { +func relativeTimeFromString(in string) (string, error) { if in == "" { return "", nil } @@ -63,6 +63,11 @@ func relativeTime(in string) (string, error) { return "", err } + return relativeTime(t), nil +} + +// TODO: Write a test for this +func relativeTime(t time.Time) string { diff := time.Since(t) hours := diff.Hours() seconds := diff.Seconds() @@ -70,32 +75,32 @@ func relativeTime(in string) (string, error) { months := int(hours / 24 / 31) switch { case months > 11: - //return t.Format("Mon Jan 2 2006"), err - return t.Format("Jan 2 2006"), err + //return t.Format("Mon Jan 2 2006") + return t.Format("Jan 2 2006") case months > 1: - return fmt.Sprintf("%d months ago", months), err + return fmt.Sprintf("%d months ago", months) case months == 1: - return "a month ago", err + return "a month ago" case weeks > 1: - return fmt.Sprintf("%d weeks ago", weeks), err + return fmt.Sprintf("%d weeks ago", weeks) case int(hours/24) == 7: - return "a week ago", err + return "a week ago" case int(hours/24) == 1: - return "1 day ago", err + return "1 day ago" case int(hours/24) > 1: - return fmt.Sprintf("%d days ago", int(hours/24)), err + return fmt.Sprintf("%d days ago", int(hours/24)) case seconds <= 1: - return "a moment ago", err + return "a moment ago" case seconds < 60: - return fmt.Sprintf("%d seconds ago", int(seconds)), err + return fmt.Sprintf("%d seconds ago", int(seconds)) case seconds < 120: - return "a minute ago", err + return "a minute ago" case seconds < 3600: - return fmt.Sprintf("%d minutes ago", int(seconds/60)), err + return fmt.Sprintf("%d minutes ago", int(seconds/60)) case seconds < 7200: - return "an hour ago", err + return "an hour ago" default: - return fmt.Sprintf("%d hours ago", int(seconds/60/60)), err + return fmt.Sprintf("%d hours ago", int(seconds/60/60)) } }