[AB-190] migrating default config (featureMode, system config, post targets, feature flags) from tables to property files

not longer immediately instantiating the feature flag instance when a new server is found, but only when its config is changed or when a feature mod has its config changed
This commit is contained in:
Sheldan
2021-02-11 00:09:58 +01:00
parent ea12d67e5f
commit 047c574319
98 changed files with 654 additions and 1356 deletions

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.assignableroles.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:assignableRoles-config.properties")
public class AssignableRolesConfig {
}

View File

@@ -0,0 +1,2 @@
abstracto.featureFlags.emoteTracking.featureName=emoteTracking
abstracto.featureFlags.emoteTracking.enabled=false

View File

@@ -9,5 +9,4 @@
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="assignableFeature" value="(SELECT id FROM feature WHERE key = 'assignableRole')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="assignableRole_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${assignableFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.experience.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:experience-config.properties")
public class ExperienceConfig {
}

View File

@@ -0,0 +1,9 @@
abstracto.systemConfigs.minExp.name=minExp
abstracto.systemConfigs.minExp.longValue=10
abstracto.systemConfigs.maxExp.name=maxExp
abstracto.systemConfigs.maxExp.longValue=25
abstracto.systemConfigs.expMultiplier.name=expMultiplier
abstracto.systemConfigs.expMultiplier.longValue=1
abstracto.featureFlags.experience.featureName=experience
abstracto.featureFlags.experience.enabled=false

View File

@@ -10,7 +10,5 @@
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="experience_job.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,28 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="experience_default_config-insert">
<insert tableName="default_config">
<column name="name" value="minExp"/>
<column name="long_value" value="10"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="maxExp"/>
<column name="long_value" value="25"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="expMultiplier"/>
<column name="double_value" value="1"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="experienceFeature" value="(SELECT id FROM feature WHERE key = 'experience')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="experience_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${experienceFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.moderation.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:moderation-config.properties")
public class ModerationConfig {
}

View File

@@ -6,13 +6,9 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="un_mute_job.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="warn_decay_job.xml" relativeToChangelogFile="true"/>
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="default_posttarget.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd">
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="moderation_default_config-insert">
<insert tableName="default_config">
<column name="name" value="decayDays"/>
<column name="long_value" value="90"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,54 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="moderationFeature" value="(SELECT id FROM feature WHERE key = 'moderation')"/>
<property name="warningsFeature" value="(SELECT id FROM feature WHERE key = 'warnings')"/>
<property name="warnDecayFeature" value="(SELECT id FROM feature WHERE key = 'warnDecay')"/>
<property name="loggingFeature" value="(SELECT id FROM feature WHERE key = 'logging')"/>
<property name="mutingFeature" value="(SELECT id FROM feature WHERE key = 'muting')"/>
<property name="userNotesFeature" value="(SELECT id FROM feature WHERE key = 'userNotes')"/>
<property name="inviteLinkFilteringFeature" value="(SELECT id FROM feature WHERE key = 'inviteFilter')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="moderation_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${moderationFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${warningsFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${warnDecayFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${loggingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${mutingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${userNotesFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,77 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="moderationFeature" value="(SELECT id FROM feature WHERE key = 'moderation')"/>
<property name="warningsFeature" value="(SELECT id FROM feature WHERE key = 'warnings')"/>
<property name="warnDecayFeature" value="(SELECT id FROM feature WHERE key = 'warnDecay')"/>
<property name="mutingFeature" value="(SELECT id FROM feature WHERE key = 'muting')"/>
<property name="inviteLinkFilteringFeature" value="(SELECT id FROM feature WHERE key = 'inviteFilter')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="moderation_default_feature_mode-insertion">
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="banLogging"/>
<column name="feature_id" valueComputed="${moderationFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="kickLogging"/>
<column name="feature_id" valueComputed="${moderationFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="warnLogging"/>
<column name="feature_id" valueComputed="${warningsFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="warnDecayLogging"/>
<column name="feature_id" valueComputed="${warningsFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="automaticWarnDecayLogging"/>
<column name="feature_id" valueComputed="${warningsFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="muteLogging"/>
<column name="feature_id" valueComputed="${mutingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="unMuteLogging"/>
<column name="feature_id" valueComputed="${mutingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="manualUnMuteLogging"/>
<column name="feature_id" valueComputed="${mutingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="trackUses"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="filterNotifications"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,52 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="moderation_default_posttarget-insertion">
<insert tableName="default_posttarget">
<column name="name" value="joinLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="leaveLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="warnLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="kickLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="banLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="editLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="deleteLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="muteLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="decayLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="inviteDeleteLog"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,76 @@
abstracto.systemConfigs.decayDays.name=decayDays
abstracto.systemConfigs.decayDays.longValue=90
abstracto.featureFlags.moderation.featureName=moderation
abstracto.featureFlags.moderation.enabled=false
abstracto.featureFlags.warnings.featureName=warnings
abstracto.featureFlags.warnings.enabled=false
abstracto.featureFlags.warnDecay.featureName=warnDecay
abstracto.featureFlags.warnDecay.enabled=false
abstracto.featureFlags.logging.featureName=logging
abstracto.featureFlags.logging.enabled=false
abstracto.featureFlags.muting.featureName=muting
abstracto.featureFlags.muting.enabled=false
abstracto.featureFlags.userNotes.featureName=userNotes
abstracto.featureFlags.userNotes.enabled=false
abstracto.featureFlags.inviteFilter.featureName=inviteFilter
abstracto.featureFlags.inviteFilter.enabled=false
abstracto.postTargets.joinLog.name=joinLog
abstracto.postTargets.leaveLog.name=leaveLog
abstracto.postTargets.warnLog.name=warnLog
abstracto.postTargets.kickLog.name=kickLog
abstracto.postTargets.banLog.name=banLog
abstracto.postTargets.editLog.name=editLog
abstracto.postTargets.deleteLog.name=deleteLog
abstracto.postTargets.muteLog.name=muteLog
abstracto.postTargets.decayLog.name=decayLog
abstracto.postTargets.inviteDeleteLog.name=inviteDeleteLog
abstracto.featureModes.banLogging.featureName=moderation
abstracto.featureModes.banLogging.mode=banLogging
abstracto.featureModes.banLogging.enabled=true
abstracto.featureModes.kickLogging.featureName=moderation
abstracto.featureModes.kickLogging.mode=kickLogging
abstracto.featureModes.kickLogging.enabled=true
abstracto.featureModes.warnLogging.featureName=warnings
abstracto.featureModes.warnLogging.mode=warnLogging
abstracto.featureModes.warnLogging.enabled=true
abstracto.featureModes.warnDecayLogging.featureName=warnings
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
abstracto.featureModes.warnDecayLogging.enabled=true
abstracto.featureModes.automaticWarnDecayLogging.featureName=warnDecay
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
abstracto.featureModes.muteLogging.featureName=muting
abstracto.featureModes.muteLogging.mode=muteLogging
abstracto.featureModes.muteLogging.enabled=true
abstracto.featureModes.unMuteLogging.featureName=muting
abstracto.featureModes.unMuteLogging.mode=unMuteLogging
abstracto.featureModes.unMuteLogging.enabled=true
abstracto.featureModes.manualUnMuteLogging.featureName=muting
abstracto.featureModes.manualUnMuteLogging.mode=manualUnMuteLogging
abstracto.featureModes.manualUnMuteLogging.enabled=true
abstracto.featureModes.trackUses.featureName=inviteFilter
abstracto.featureModes.trackUses.mode=trackUses
abstracto.featureModes.trackUses.enabled=true
abstracto.featureModes.filterNotifications.featureName=inviteFilter
abstracto.featureModes.filterNotifications.mode=filterNotifications
abstracto.featureModes.filterNotifications.enabled=true

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.modmail.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:modmail-config.properties")
public class ModMailConfig {
}

View File

@@ -6,12 +6,8 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="default_posttarget.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_emote.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd">
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="modMailClosingText-insert">
<insert tableName="default_config">
<column name="name" value="modMailClosingText"/>
<column name="string_value" value="Thread has been closed."/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="modmailFeature" value="(SELECT id FROM feature WHERE key = 'modmail')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="modmail_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${modmailFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,25 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="modmailFeature" value="(SELECT id FROM feature WHERE key = 'modmail')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="modmail_default_feature_mode-insertion">
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="log"/>
<column name="feature_id" valueComputed="${modmailFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="threadMessage"/>
<column name="feature_id" valueComputed="${modmailFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,17 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="modmail_default_posttarget-insertion">
<insert tableName="default_posttarget">
<column name="name" value="modmailLog"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="modmailPing"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
abstracto.systemConfigs.modMailClosingText.name=modMailClosingText
abstracto.systemConfigs.modMailClosingText.stringValue=Thread has been closed.
abstracto.featureFlags.modmail.featureName=modmail
abstracto.featureFlags.modmail.enabled=false
abstracto.postTargets.modmailLog.name=modmailLog
abstracto.postTargets.modmailPing.name=modmailPing
abstracto.featureModes.log.featureName=modmail
abstracto.featureModes.log.mode=log
abstracto.featureModes.log.enabled=true
abstracto.featureModes.threadMessage.featureName=modmail
abstracto.featureModes.threadMessage.mode=filterNotifications
abstracto.featureModes.threadMessage.enabled=true

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.statistic.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:statistic-config.properties")
public class StatisticConfig {
}

View File

@@ -7,7 +7,7 @@
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="statisticModule" value="(SELECT id FROM module WHERE name = 'statistic')"/>
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emoteTracking')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="statistic-commands">

View File

@@ -8,8 +8,6 @@
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="emote_statistic_job.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="emote_tracking_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,31 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="emote_tracking_default_feature_mode-insertion">
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="emoteAutoTrack"/>
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="false"/>
<column name="mode" value="externalEmotes"/>
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="false"/>
<column name="mode" value="autoTrackExternal"/>
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -9,7 +9,7 @@
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="emote_tracking_feature-insertion">
<insert tableName="feature">
<column name="key" value="emote_tracking"/>
<column name="key" value="emoteTracking"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>

View File

@@ -0,0 +1,15 @@
abstracto.featureFlags.assignableRole.featureName=assignableRole
abstracto.featureFlags.assignableRole.enabled=false
abstracto.featureModes.emoteAutoTrack.featureName=emoteTracking
abstracto.featureModes.emoteAutoTrack.mode=emoteAutoTrack
abstracto.featureModes.emoteAutoTrack.enabled=true
abstracto.featureModes.externalEmotes.featureName=emoteTracking
abstracto.featureModes.externalEmotes.mode=externalEmotes
abstracto.featureModes.externalEmotes.enabled=false
abstracto.featureModes.autoTrackExternal.featureName=emoteTracking
abstracto.featureModes.autoTrackExternal.mode=autoTrackExternal
abstracto.featureModes.autoTrackExternal.enabled=false

View File

@@ -9,7 +9,7 @@ public enum StatisticFeatures implements FeatureEnum {
/**
* Feature responsible to track the emotes used in a message on a server.
*/
EMOTE_TRACKING("emote_tracking");
EMOTE_TRACKING("emoteTracking");
private final String key;

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.utility.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:utility-config.properties")
public class UtilityConfig {
}

View File

@@ -6,14 +6,10 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="default_emote.xml" relativeToChangelogFile="true"/>
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="default_posttarget.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="reminder_job.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
<include file="channel_group_types.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,50 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="starLevels-insert">
<insert tableName="default_config">
<column name="name" value="starLvl1"/>
<column name="long_value" value="5"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="starLvl2"/>
<column name="long_value" value="8"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="starLvl3"/>
<column name="long_value" value="13"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="starLvl4"/>
<column name="long_value" value="17"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="starLvls"/>
<column name="long_value" value="4"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
<changeSet author="Sheldan" id="entertainment_default_config-insert">
<insert tableName="default_config">
<column name="name" value="rouletteBullets"/>
<column name="long_value" value="6"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_config">
<column name="name" value="rollDefaultHigh"/>
<column name="long_value" value="6"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,56 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="starboardFeature" value="(SELECT id FROM feature WHERE key = 'starboard')"/>
<property name="remindFeature" value="(SELECT id FROM feature WHERE key = 'remind')"/>
<property name="suggestionFeature" value="(SELECT id FROM feature WHERE key = 'suggestion')"/>
<property name="utilityFeature" value="(SELECT id FROM feature WHERE key = 'utility')"/>
<property name="linkEmbedFeature" value="(SELECT id FROM feature WHERE key = 'link_embeds')"/>
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<property name="entertainmentFeature" value="(SELECT id FROM feature WHERE key = 'entertainment')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utility_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${starboardFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${remindFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${suggestionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${utilityFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${linkEmbedFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
<changeSet author="Sheldan" id="utility_entertainment_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${entertainmentFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,25 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utilities_default_feature_mode-insertion">
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="download"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="leaderboard"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,20 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utility_default_posttarget-insertion">
<insert tableName="default_posttarget">
<column name="name" value="suggestions"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_posttarget">
<column name="name" value="starboard"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -25,7 +25,7 @@
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="feature">
<column name="key" value="link_embeds"/>
<column name="key" value="linkEmbeds"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="feature">

View File

@@ -0,0 +1,52 @@
abstracto.systemConfigs.starLvl1.name=starLvl1
abstracto.systemConfigs.starLvl1.longValue=5
abstracto.systemConfigs.starLvl2.name=starLvl2
abstracto.systemConfigs.starLvl2.longValue=8
abstracto.systemConfigs.starLvl3.name=starLvl3
abstracto.systemConfigs.starLvl3.longValue=13
abstracto.systemConfigs.starLvl4.name=starLvl4
abstracto.systemConfigs.starLvl4.longValue=17
abstracto.systemConfigs.starLvls.name=starLvls
abstracto.systemConfigs.starLvls.longValue=4
abstracto.systemConfigs.rouletteBullets.name=rouletteBullets
abstracto.systemConfigs.rouletteBullets.longValue=6
abstracto.systemConfigs.rollDefaultHigh.name=rollDefaultHigh
abstracto.systemConfigs.rollDefaultHigh.longValue=6
abstracto.featureFlags.starboard.featureName=starboard
abstracto.featureFlags.starboard.enabled=false
abstracto.featureFlags.remind.featureName=remind
abstracto.featureFlags.remind.enabled=false
abstracto.featureFlags.suggestion.featureName=suggestion
abstracto.featureFlags.suggestion.enabled=false
abstracto.featureFlags.utility.featureName=utility
abstracto.featureFlags.utility.enabled=false
abstracto.featureFlags.linkEmbeds.featureName=linkEmbeds
abstracto.featureFlags.linkEmbeds.enabled=false
abstracto.featureFlags.repostDetection.featureName=repostDetection
abstracto.featureFlags.repostDetection.enabled=false
abstracto.featureFlags.entertainment.featureName=entertainment
abstracto.featureFlags.entertainment.enabled=false
abstracto.postTargets.suggestions.name=suggestions
abstracto.postTargets.starboard.name=starboard
abstracto.featureModes.download.featureName=repostDetection
abstracto.featureModes.download.mode=download
abstracto.featureModes.download.enabled=true
abstracto.featureModes.leaderboard.featureName=repostDetection
abstracto.featureModes.leaderboard.mode=leaderboard
abstracto.featureModes.leaderboard.enabled=true

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.config;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
@@ -9,10 +9,7 @@ import dev.sheldan.abstracto.utility.service.StarboardServiceBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
@@ -38,7 +35,8 @@ public class StarboardConfigListenerTest {
public void testUpdateServerConfig() {
AServer server = MockUtils.getServer();
int numberOfLevels = 4;
ADefaultConfig config = ADefaultConfig.builder().longValue((long)numberOfLevels).build();
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
when(config.getLongValue()).thenReturn((long) numberOfLevels);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LVL_CONFIG_PREFIX + 1)).thenReturn(config);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LVL_CONFIG_PREFIX + 2)).thenReturn(config);

View File

@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.*;
@@ -146,7 +147,7 @@ public class StarboardServiceBeanTest {
when(memberService.getMemberInServerAsync(SERVER_ID, STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
when(channelService.getTextChannelFromServerOptional(SERVER_ID, CHANNEL_ID)).thenReturn(Optional.of(mockedTextChannel));
when(guildService.getGuildByIdOptional(SERVER_ID)).thenReturn(Optional.of(guild));
ADefaultConfig config = Mockito.mock(ADefaultConfig.class);
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
when(config.getLongValue()).thenReturn(3L);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
when(configService.getLongValue("starLvl3", SERVER_ID)).thenReturn(3L);
@@ -219,7 +220,7 @@ public class StarboardServiceBeanTest {
when(templateService.renderEmbedTemplate(eq(STARBOARD_POST_TEMPLATE), starboardPostModelArgumentCaptor.capture())).thenReturn(postMessage);
when(postTargetService.editOrCreatedInPostTarget(oldPostId, postMessage, StarboardPostTarget.STARBOARD, SERVER_ID)).thenReturn(Arrays.asList(CompletableFuture.completedFuture(sendPost)));
when(sendPost.getIdLong()).thenReturn(newPostId);
ADefaultConfig config = Mockito.mock(ADefaultConfig.class);
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
when(config.getLongValue()).thenReturn(4L);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
when(starboardPostManagementService.findByStarboardPostId(starboardPostId)).thenReturn(Optional.of(post));

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.validator;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.FeatureValidatorService;
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
@@ -9,10 +9,7 @@ import dev.sheldan.abstracto.utility.service.StarboardServiceBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
@@ -38,7 +35,8 @@ public class StarboardFeatureValidatorServiceTest {
public void testStarboardFeatureConfig() {
AServer server = MockUtils.getServer();
int levelCount = 4;
ADefaultConfig config = ADefaultConfig.builder().longValue((long)levelCount).build();
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
when(config.getLongValue()).thenReturn((long) levelCount);
when(defaultConfigManagementService.getDefaultConfig(StarboardServiceBean.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
testUnit.featureIsSetup(null, server, null);

View File

@@ -6,7 +6,7 @@ import lombok.Getter;
@Getter
public enum UtilityFeature implements FeatureEnum {
REMIND("remind"), STARBOARD("starboard"), SUGGEST("suggestion"), UTILITY("utility"),
LINK_EMBEDS("link_embeds"), REPOST_DETECTION("repostDetection"), ENTERTAINMENT("entertainment");
LINK_EMBEDS("linkEmbeds"), REPOST_DETECTION("repostDetection"), ENTERTAINMENT("entertainment");
private String key;

View File

@@ -12,8 +12,10 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.converter.FeatureFlagConverter;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import dev.sheldan.abstracto.core.models.template.commands.FeaturesModel;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
@@ -22,8 +24,10 @@ import dev.sheldan.abstracto.templating.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Component
public class Features extends AbstractConditionableCommand {
@@ -40,6 +44,9 @@ public class Features extends AbstractConditionableCommand {
@Autowired
private FeatureFlagConverter featureFlagConverter;
@Autowired
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
@Autowired
private ServerManagementService serverManagementService;
@@ -47,8 +54,21 @@ public class Features extends AbstractConditionableCommand {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
AServer server = serverManagementService.loadServer(commandContext.getGuild());
List<AFeatureFlag> features = featureFlagManagementService.getFeatureFlagsOfServer(server);
List<FeatureFlagProperty> defaultFeatureFlagProperties = defaultFeatureFlagManagementService.getAllDefaultFeatureFlags();
FeaturesModel featuresModel = (FeaturesModel) ContextConverter.fromCommandContext(commandContext, FeaturesModel.class);
features.sort(Comparator.comparing(o -> o.getFeature().getKey()));
featuresModel.setFeatures(featureFlagConverter.fromFeatureFlags(features));
defaultFeatureFlagProperties = defaultFeatureFlagProperties
.stream()
.filter(featureFlagProperty ->
features
.stream()
.noneMatch(aFeatureFlag ->
aFeatureFlag.getFeature().getKey()
.equals(featureFlagProperty.getFeatureName())))
.collect(Collectors.toList());
defaultFeatureFlagProperties.sort(Comparator.comparing(FeatureFlagProperty::getFeatureName));
featuresModel.setDefaultFeatures(featureFlagConverter.fromFeatureFlagProperties(defaultFeatureFlagProperties));
MessageToSend messageToSend = templateService.renderEmbedTemplate("features_response", featuresModel);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(aVoid -> CommandResult.fromIgnored());

View File

@@ -0,0 +1,23 @@
package dev.sheldan.abstracto.core.config;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import dev.sheldan.abstracto.core.models.property.PostTargetProperty;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "abstracto")
public class DefaultConfigProperties {
private Map<String, SystemConfigProperty> systemConfigs;
private Map<String, FeatureFlagProperty> featureFlags;
private Map<String, PostTargetProperty> postTargets;
private Map<String, FeatureModeProperty> featureModes;
}

View File

@@ -3,6 +3,8 @@ package dev.sheldan.abstracto.core.converter;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import dev.sheldan.abstracto.core.models.template.commands.DefaultFeatureFlagDisplay;
import dev.sheldan.abstracto.core.models.template.commands.FeatureFlagDisplay;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -27,7 +29,21 @@ public class FeatureFlagConverter {
.build();
}
public DefaultFeatureFlagDisplay fromFeatureFlagProperty(FeatureFlagProperty featureFlagProperty) {
FeatureEnum featureEnum = featureFlagService.getFeatureEnum(featureFlagProperty.getFeatureName());
FeatureConfig forFeature = featureFlagService.getFeatureDisplayForFeature(featureEnum);
return DefaultFeatureFlagDisplay
.builder()
.featureConfig(forFeature)
.featureFlagProperty(featureFlagProperty)
.build();
}
public List<FeatureFlagDisplay> fromFeatureFlags(List<AFeatureFlag> featureFlags) {
return featureFlags.stream().map(this::fromAFeatureFlag).collect(Collectors.toList());
}
public List<DefaultFeatureFlagDisplay> fromFeatureFlagProperties(List<FeatureFlagProperty> featureFlags) {
return featureFlags.stream().map(this::fromFeatureFlagProperty).collect(Collectors.toList());
}
}

View File

@@ -1,9 +1,9 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AConfig;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.commands.SetupSystemConfigMessageModel;
import dev.sheldan.abstracto.core.service.ConfigService;
@@ -52,7 +52,7 @@ public class SystemConfigSetupStep extends AbstractConfigSetupStep {
@Override
public CompletableFuture<SetupStepResult> execute(AServerChannelUserId user, SetupStepParameter parameter) {
SystemConfigStepParameter systemConfigStepParameter = (SystemConfigStepParameter) parameter;
ADefaultConfig defaultConfig = defaultConfigManagementService.getDefaultConfig(systemConfigStepParameter.getConfigKey());
SystemConfigProperty defaultConfig = defaultConfigManagementService.getDefaultConfig(systemConfigStepParameter.getConfigKey());
SetupSystemConfigMessageModel model = SetupSystemConfigMessageModel
.builder()
.configKey(systemConfigStepParameter.getConfigKey())
@@ -108,7 +108,7 @@ public class SystemConfigSetupStep extends AbstractConfigSetupStep {
@Transactional
public AConfig loadDefaultConfig(SystemConfigStepParameter systemConfigStepParameter) {
AConfig config;
ADefaultConfig defaultConfig = defaultConfigManagementService.getDefaultConfig(systemConfigStepParameter.getConfigKey());
SystemConfigProperty defaultConfig = defaultConfigManagementService.getDefaultConfig(systemConfigStepParameter.getConfigKey());
config = AConfig
.builder()
.name(defaultConfig.getName())

View File

@@ -1,35 +0,0 @@
package dev.sheldan.abstracto.core.listener.sync.entity;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class FeatureFlagListener implements ServerConfigListener {
@Autowired
private FeatureFlagManagementService service;
@Autowired
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
@Override
public void updateServerConfig(AServer server) {
log.info("Setting up feature flags if necessary.");
defaultFeatureFlagManagementService.getAllDefaultFeatureFlags().forEach(defaultFeatureFlag -> {
AFeature feature = defaultFeatureFlag.getFeature();
if(!service.featureFlagExists(feature, server)) {
log.info("Creating feature flag {} for server {}.", feature.getKey(), server.getId());
service.createFeatureFlag(feature, server.getId(), defaultFeatureFlag.isEnabled());
} else {
log.trace("Feature flag {} for server {} already exists.", feature.getKey(), server.getId());
}
});
}
}

View File

@@ -1,17 +0,0 @@
package dev.sheldan.abstracto.core.repository;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
@Repository
public interface DefaultConfigRepository extends JpaRepository<ADefaultConfig, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
ADefaultConfig findByName(String name);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
boolean existsByName(String name);
}

View File

@@ -1,18 +0,0 @@
package dev.sheldan.abstracto.core.repository;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureFlag;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
@Repository
public interface DefaultFeatureFlagRepository extends JpaRepository<DefaultFeatureFlag, Long> {
@NotNull
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<DefaultFeatureFlag> findAll();
}

View File

@@ -1,20 +0,0 @@
package dev.sheldan.abstracto.core.repository;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
import java.util.Optional;
@Repository
public interface DefaultFeatureModeRepository extends JpaRepository<DefaultFeatureMode, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<DefaultFeatureMode> findByFeature(AFeature feature);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Optional<DefaultFeatureMode> findByFeatureAndMode(AFeature feature, String mode);
}

View File

@@ -1,18 +0,0 @@
package dev.sheldan.abstracto.core.repository;
import dev.sheldan.abstracto.core.models.database.DefaultPostTarget;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
@Repository
public interface DefaultPostTargetRepository extends JpaRepository<DefaultPostTarget, Long> {
@NotNull
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<DefaultPostTarget> findAll();
}

View File

@@ -8,11 +8,12 @@ import org.springframework.data.jpa.repository.QueryHints;
import javax.persistence.QueryHint;
import java.util.List;
import java.util.Optional;
public interface FeatureFlagRepository extends JpaRepository<AFeatureFlag, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
AFeatureFlag findByServerAndFeature(AServer server, AFeature key);
Optional<AFeatureFlag> findByServerAndFeature(AServer server, AFeature key);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
boolean existsByServerAndFeature(AServer server, AFeature key);

View File

@@ -15,7 +15,7 @@ import java.util.Optional;
public interface FeatureModeRepository extends JpaRepository<AFeatureMode, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Optional<AFeatureMode> findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(AServer server, AFeature feature, String mode);
Optional<AFeatureMode> findByServerAndFeatureFlag_FeatureAndFeatureMode(AServer server, AFeature feature, String mode);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<AFeatureMode> findByServer(AServer server);

View File

@@ -7,11 +7,15 @@ import dev.sheldan.abstracto.core.exception.FeatureNotFoundException;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class FeatureFlagServiceBean implements FeatureFlagService {
@@ -27,6 +31,9 @@ public class FeatureFlagServiceBean implements FeatureFlagService {
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
@Override
public boolean isFeatureEnabled(FeatureConfig name, Long serverId) {
return getFeatureFlagValue(name.getFeature(), serverId);
@@ -67,6 +74,18 @@ public class FeatureFlagServiceBean implements FeatureFlagService {
updateFeatureFlag(feature, server, false);
}
@Override
public AFeatureFlag createInstanceFromDefaultConfig(FeatureEnum name, Long serverId) {
FeatureFlagProperty defaultFeatureFlag = defaultFeatureFlagManagementService.getDefaultFeatureFlagProperty(name);
return updateFeatureFlag(name, serverId, defaultFeatureFlag.getEnabled());
}
@Override
public AFeatureFlag createInstanceFromDefaultConfig(FeatureEnum name, AServer server) {
FeatureFlagProperty defaultFeatureFlag = defaultFeatureFlagManagementService.getDefaultFeatureFlagProperty(name);
return updateFeatureFlag(name, server, defaultFeatureFlag.getEnabled());
}
@Override
public boolean getFeatureFlagValue(FeatureEnum key, Long serverId) {
AServer server = serverManagementService.loadOrCreate(serverId);
@@ -76,8 +95,10 @@ public class FeatureFlagServiceBean implements FeatureFlagService {
@Override
public boolean getFeatureFlagValue(FeatureEnum key, AServer server) {
AFeature feature = featureManagementService.getFeature(key.getKey());
AFeatureFlag featureFlag = managementService.getFeatureFlag(feature, server);
return featureFlag.isEnabled();
Optional<AFeatureFlag> featureFlagOptional = managementService.getFeatureFlag(feature, server);
return featureFlagOptional
.map(AFeatureFlag::isEnabled)
.orElseGet(() -> defaultFeatureFlagManagementService.getDefaultFeatureFlagProperty(feature).getEnabled());
}
@Override

View File

@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
@@ -29,6 +30,9 @@ public class FeatureModeServiceBean implements FeatureModeService {
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureManagementService featureManagementService;
@@ -43,13 +47,18 @@ public class FeatureModeServiceBean implements FeatureModeService {
@Override
public void enableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
setOrCreateFeatureMode(featureEnum, server, mode, true);
}
private void setOrCreateFeatureMode(FeatureEnum featureEnum, AServer server, FeatureMode mode, boolean featureModeState) {
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
Optional<AFeatureMode> existing = featureModeManagementService.getFeatureMode(feature, server, mode);
if(existing.isPresent()) {
existing.get().setEnabled(true);
if (existing.isPresent()) {
existing.get().setEnabled(featureModeState);
} else {
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
featureModeManagementService.createMode(featureFlag, mode, true);
Optional<AFeatureFlag> featureFlagOptional = featureFlagManagementService.getFeatureFlag(feature, server);
AFeatureFlag featureFlagInstance = featureFlagOptional.orElseGet(() -> featureFlagService.createInstanceFromDefaultConfig(featureEnum, server));
featureModeManagementService.createMode(featureFlagInstance, mode, featureModeState);
}
}
@@ -64,14 +73,7 @@ public class FeatureModeServiceBean implements FeatureModeService {
@Override
public void disableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
Optional<AFeatureMode> existing = featureModeManagementService.getFeatureMode(feature, server, mode);
if(existing.isPresent()) {
existing.get().setEnabled(false);
} else {
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
featureModeManagementService.createMode(featureFlag, mode, false);
}
setOrCreateFeatureMode(featureEnum, server, mode, false);
}
@Override
@@ -80,7 +82,7 @@ public class FeatureModeServiceBean implements FeatureModeService {
if(featureModeManagementService.doesFeatureModeExist(feature, server, mode)) {
return featureModeManagementService.isFeatureModeActive(feature, server, mode);
} else {
return defaultFeatureModeManagement.getFeatureMode(feature, mode.getKey()).isEnabled();
return defaultFeatureModeManagement.getFeatureMode(feature, mode.getKey()).getEnabled();
}
}
@@ -116,19 +118,19 @@ public class FeatureModeServiceBean implements FeatureModeService {
@Override
public List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server) {
List<DefaultFeatureMode> allDefaultModes = defaultFeatureModeManagement.getAll();
List<FeatureModeProperty> allDefaultModes = defaultFeatureModeManagement.getAll();
List<AFeatureMode> allModesFromServer = featureModeManagementService.getFeatureModesOfServer(server);
return combineFeatureModesWithDefault(server, allDefaultModes, allModesFromServer);
}
private List<FeatureModeDisplay> combineFeatureModesWithDefault(AServer server, List<DefaultFeatureMode> allDefaultModes, List<AFeatureMode> allModesFromServer) {
private List<FeatureModeDisplay> combineFeatureModesWithDefault(AServer server, List<FeatureModeProperty> allDefaultModes, List<AFeatureMode> allModesFromServer) {
List<FeatureModeDisplay> result = new ArrayList<>();
List<AFeatureMode> activeModes = allModesFromServer.stream().filter(AFeatureMode::getEnabled).collect(Collectors.toList());
List<AFeatureMode> disabledModes = allModesFromServer.stream().filter(aFeatureMode -> !aFeatureMode.getEnabled()).collect(Collectors.toList());
List<String> usedModes = allModesFromServer.stream().map(aFeatureMode -> aFeatureMode.getFeatureMode().getMode()).collect(Collectors.toList());
List<String> usedModes = allModesFromServer.stream().map(AFeatureMode::getFeatureMode).collect(Collectors.toList());
HashMap<String, FeatureConfig> featureConfigCache = new HashMap<>();
Consumer<AFeatureMode> loadUsedValues = aFeatureMode -> {
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, aFeatureMode.getFeatureFlag().getFeature());
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, aFeatureMode.getFeatureFlag().getFeature().getKey());
FeatureModeDisplay featureModeDisplay = FeatureModeDisplay
.builder()
.featureMode(aFeatureMode)
@@ -141,9 +143,10 @@ public class FeatureModeServiceBean implements FeatureModeService {
disabledModes.forEach(loadUsedValues);
allDefaultModes.forEach(defaultFeatureMode -> {
if(!usedModes.contains(defaultFeatureMode.getMode())) {
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, defaultFeatureMode.getFeature());
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(defaultFeatureMode.getFeature(), server);
AFeatureMode fakeMode = AFeatureMode.builder().server(server).enabled(defaultFeatureMode.isEnabled()).featureMode(defaultFeatureMode).featureFlag(featureFlag).build();
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, defaultFeatureMode.getFeatureName());
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(defaultFeatureMode.getFeatureName(), server).orElse(null);
// TODO refactor this to a separate display model, instead of building the AFeatureMode instance
AFeatureMode fakeMode = AFeatureMode.builder().server(server).enabled(defaultFeatureMode.getEnabled()).featureMode(defaultFeatureMode.getMode()).featureFlag(featureFlag).build();
FeatureModeDisplay featureModeDisplay = FeatureModeDisplay
.builder()
.featureMode(fakeMode)
@@ -156,13 +159,12 @@ public class FeatureModeServiceBean implements FeatureModeService {
return result;
}
private FeatureConfig getFeatureConfig(HashMap<String, FeatureConfig> featureConfigs, AFeature feature) {
String featureKey = feature.getKey();
private FeatureConfig getFeatureConfig(HashMap<String, FeatureConfig> featureConfigs, String featureKey) {
FeatureConfig featureConfig;
if (featureConfigs.containsKey(featureKey)) {
featureConfig = featureConfigs.get(featureKey);
} else {
featureConfig = featureConfigService.getFeatureConfigForFeature(feature);
featureConfig = featureConfigService.getFeatureDisplayForFeature(featureKey);
featureConfigs.put(featureKey, featureConfig);
}
return featureConfig;
@@ -170,7 +172,7 @@ public class FeatureModeServiceBean implements FeatureModeService {
@Override
public List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server, AFeature feature) {
List<DefaultFeatureMode> allDefaultModes = defaultFeatureModeManagement.getFeatureModesForFeature(feature);
List<FeatureModeProperty> allDefaultModes = defaultFeatureModeManagement.getFeatureModesForFeature(feature);
List<AFeatureMode> allModesFromServer = featureModeManagementService.getFeatureModesOfFeatureInServer(server, feature);
return combineFeatureModesWithDefault(server, allDefaultModes, allModesFromServer);
}

View File

@@ -18,7 +18,6 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.apache.commons.collections4.SetUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.security.auth.login.LoginException;

View File

@@ -1,7 +1,7 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.repository.DefaultConfigRepository;
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -11,61 +11,10 @@ import org.springframework.stereotype.Component;
public class DefaultConfigManagementServiceBean implements DefaultConfigManagementService {
@Autowired
private DefaultConfigRepository defaultConfigRepository;
private DefaultConfigProperties defaultConfigProperties;
@Override
public void createDefaultConfig(String key, String value) {
ADefaultConfig build;
if(defaultConfigRepository.existsByName(key)) {
build = defaultConfigRepository.findByName(key);
build.setStringValue(value);
} else {
build = ADefaultConfig
.builder()
.name(key)
.stringValue(value)
.build();
log.trace("Creating default config entry with type string for key {}.", key);
}
defaultConfigRepository.save(build);
}
@Override
public void createDefaultConfig(String key, Long value) {
ADefaultConfig build;
if(defaultConfigRepository.existsByName(key)) {
build = defaultConfigRepository.findByName(key);
build.setLongValue(value);
} else {
build = ADefaultConfig
.builder()
.name(key)
.longValue(value)
.build();
log.trace("Creating default config entry with type long for key {}.", key);
}
defaultConfigRepository.save(build);
}
@Override
public void createDefaultConfig(String key, Double value) {
ADefaultConfig build;
if(defaultConfigRepository.existsByName(key)) {
build = defaultConfigRepository.findByName(key);
build.setDoubleValue(value);
} else {
build = ADefaultConfig
.builder()
.name(key)
.doubleValue(value)
.build();
log.trace("Creating default config entry with type double for key {}.", key);
}
defaultConfigRepository.save(build);
}
@Override
public ADefaultConfig getDefaultConfig(String key) {
return defaultConfigRepository.findByName(key);
public SystemConfigProperty getDefaultConfig(String key) {
return defaultConfigProperties.getSystemConfigs().get(key);
}
}

View File

@@ -1,26 +1,46 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureFlag;
import dev.sheldan.abstracto.core.repository.DefaultFeatureFlagRepository;
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class DefaultFeatureFlagManagementServiceBean implements DefaultFeatureFlagManagementService{
@Autowired
private DefaultFeatureFlagRepository repository;
private DefaultConfigProperties defaultConfigProperties;
@Override
public List<String> getDefaultFeatureKeys() {
return repository.findAll().stream().map(defaultFeatureFlag -> defaultFeatureFlag.getFeature().getKey()).collect(Collectors.toList());
return new ArrayList<>(defaultConfigProperties.getFeatureFlags().keySet());
}
@Override
public List<DefaultFeatureFlag> getAllDefaultFeatureFlags() {
return repository.findAll();
public FeatureFlagProperty getDefaultFeatureFlagProperty(AFeature feature) {
return findFeatureFlagPropertyViaFeatureKey(feature.getKey());
}
@Override
public FeatureFlagProperty getDefaultFeatureFlagProperty(FeatureEnum feature) {
return findFeatureFlagPropertyViaFeatureKey(feature.getKey());
}
@Override
public List<FeatureFlagProperty> getAllDefaultFeatureFlags() {
return new ArrayList<>(defaultConfigProperties.getFeatureFlags().values());
}
private FeatureFlagProperty findFeatureFlagPropertyViaFeatureKey(String featureKey) {
return getAllDefaultFeatureFlags()
.stream()
.filter(featureFlagProperty -> featureFlagProperty.getFeatureName().equals(featureKey)).findFirst()
.orElseThrow(() -> new AbstractoRunTimeException(String.format("Feature flag for feature %s has no default value.", featureKey)));
}
}

View File

@@ -1,42 +1,51 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
import dev.sheldan.abstracto.core.repository.DefaultFeatureModeRepository;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Component
public class DefaultFeatureModeManagementBean implements DefaultFeatureModeManagement {
@Autowired
private DefaultFeatureModeRepository defaultFeatureModeRepository;
private DefaultConfigProperties defaultConfigProperties;
@Autowired
private FeatureConfigService featureConfigService;
@Override
public List<DefaultFeatureMode> getFeatureModesForFeature(AFeature feature) {
return defaultFeatureModeRepository.findByFeature(feature);
public List<FeatureModeProperty> getFeatureModesForFeature(AFeature feature) {
return defaultConfigProperties
.getFeatureModes()
.values()
.stream()
.filter(featureModeProperty -> featureModeProperty.getFeatureName().equals(feature.getKey()))
.collect(Collectors.toList());
}
@Override
public List<DefaultFeatureMode> getAll() {
return defaultFeatureModeRepository.findAll();
public List<FeatureModeProperty> getAll() {
return new ArrayList<>(defaultConfigProperties.getFeatureModes().values());
}
@Override
public Optional<DefaultFeatureMode> getFeatureModeOptional(AFeature feature, String mode) {
return defaultFeatureModeRepository.findByFeatureAndMode(feature, mode);
public Optional<FeatureModeProperty> getFeatureModeOptional(AFeature feature, String mode) {
return Optional.ofNullable(defaultConfigProperties
.getFeatureModes()
.get(mode));
}
@Override
public DefaultFeatureMode getFeatureMode(AFeature feature, String mode) {
public FeatureModeProperty getFeatureMode(AFeature feature, String mode) {
return getFeatureModeOptional(feature, mode).orElseThrow(() -> new FeatureModeNotFoundException(mode, featureConfigService.getFeatureModesFromFeatureAsString(feature.getKey())));
}
}

View File

@@ -1,10 +1,11 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.DefaultPostTarget;
import dev.sheldan.abstracto.core.repository.DefaultPostTargetRepository;
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
import dev.sheldan.abstracto.core.models.property.PostTargetProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -12,15 +13,15 @@ import java.util.stream.Collectors;
public class DefaultPostTargetManagementServiceBean implements DefaultPostTargetManagementService {
@Autowired
private DefaultPostTargetRepository repository;
private DefaultConfigProperties defaultConfigProperties;
@Override
public List<DefaultPostTarget> getAllDefaultPostTargets() {
return repository.findAll();
public List<PostTargetProperty> getAllDefaultPostTargets() {
return new ArrayList<>(defaultConfigProperties.getPostTargets().values());
}
@Override
public List<String> getDefaultPostTargetKeys() {
return getAllDefaultPostTargets().stream().map(DefaultPostTarget::getName).collect(Collectors.toList());
return getAllDefaultPostTargets().stream().map(PostTargetProperty::getName).collect(Collectors.toList());
}
}

View File

@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
@@ -45,18 +46,30 @@ public class FeatureFlagManagementServiceBean implements FeatureFlagManagementSe
@Override
public AFeatureFlag getFeatureFlag(AFeature feature, Long serverId) {
public Optional<AFeatureFlag> getFeatureFlag(AFeature feature, Long serverId) {
AServer server = serverManagementService.loadOrCreate(serverId);
return getFeatureFlag(feature, server);
}
@Override
public Optional<AFeatureFlag> getFeatureFlag(String featureKey, Long serverId) {
AFeature feature = featureManagementService.getFeature(featureKey);
return getFeatureFlag(feature, serverId);
}
@Override
public Optional<AFeatureFlag> getFeatureFlag(String featureKey, AServer server) {
AFeature feature = featureManagementService.getFeature(featureKey);
return getFeatureFlag(feature, server);
}
@Override
public boolean featureFlagExists(AFeature feature, AServer server) {
return repository.existsByServerAndFeature(server, feature);
}
@Override
public AFeatureFlag getFeatureFlag(AFeature feature, AServer server) {
public Optional<AFeatureFlag> getFeatureFlag(AFeature feature, AServer server) {
return repository.findByServerAndFeature(server, feature);
}
@@ -73,9 +86,15 @@ public class FeatureFlagManagementServiceBean implements FeatureFlagManagementSe
@Override
public AFeatureFlag setFeatureFlagValue(AFeature feature, AServer server, Boolean newValue) {
AFeatureFlag featureFlag = getFeatureFlag(feature, server);
featureFlag.setEnabled(newValue);
log.info("Setting feature flag for feature {} in server {} to value {}.", feature.getKey(), server.getId(), newValue);
return featureFlag;
Optional<AFeatureFlag> featureFlagOptional = getFeatureFlag(feature, server);
if(!featureFlagOptional.isPresent()) {
log.info("Setting feature flag for feature {} in server {} to value {}.", feature.getKey(), server.getId(), newValue);
return createFeatureFlag(feature, server, newValue);
}
else {
AFeatureFlag featureFlag = featureFlagOptional.get();
featureFlag.setEnabled(newValue);
return featureFlag;
}
}
}

View File

@@ -25,13 +25,12 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
@Override
public AFeatureMode createMode(AFeatureFlag featureFlag, String mode, boolean enabled) {
DefaultFeatureMode defaultMode = defaultFeatureModeManagement.getFeatureMode(featureFlag.getFeature(), mode);
AFeatureMode aFeatureMode = AFeatureMode
.builder()
.featureFlag(featureFlag)
.server(featureFlag.getServer())
.enabled(enabled)
.featureMode(defaultMode)
.featureMode(mode)
.build();
featureModeRepository.save(aFeatureMode);
@@ -40,7 +39,7 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
@Override
public boolean isFeatureModeActive(AFeature aFeature, AServer server, FeatureMode mode) {
Optional<AFeatureMode> featureModeOptional = featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, mode.getKey());
Optional<AFeatureMode> featureModeOptional = featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, aFeature, mode.getKey());
return featureModeOptional.isPresent() && featureModeOptional.get().getEnabled();
}
@@ -51,7 +50,7 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
@Override
public boolean doesFeatureModeExist(AFeature aFeature, AServer server, String modeKey) {
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, modeKey).isPresent();
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, aFeature, modeKey).isPresent();
}
@Override
@@ -61,7 +60,7 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
@Override
public Optional<AFeatureMode> getFeatureMode(AFeature aFeature, AServer server, String modeKey) {
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, modeKey);
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, aFeature, modeKey);
}
@Override

View File

@@ -6,4 +6,12 @@ server.port=8080
abstracto.allowedmention.everyone=false
abstracto.allowedmention.role=true
abstracto.allowedmention.user=true
abstracto.allowedmention.user=true
abstracto.systemConfigs.prefix.name=prefix
abstracto.systemConfigs.prefix.stringValue=!
abstracto.featureFlags.core.featureName=core
abstracto.featureFlags.core.enabled=true

View File

@@ -9,8 +9,6 @@
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="lock.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="default_emote.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="prefix-insert">
<insert tableName="default_config">
<column name="string_value" value="!"/>
<column name="name" value="prefix"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,18 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="coreFeature" value="(SELECT id FROM feature WHERE key = 'core')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="core_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="true"/>
<column name="feature_id" valueComputed="${coreFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -1,35 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="default_config-table">
<createTable tableName="default_config">
<column autoIncrement="true" name="id" type="INTEGER">
<constraints nullable="false" primaryKey="true" primaryKeyName="default_config_pkey"/>
</column>
<column name="double_value" type="FLOAT8"/>
<column name="long_value" type="BIGINT"/>
<column name="name" type="VARCHAR(255)">
<constraints nullable="true"/>
</column>
<column name="string_value" type="VARCHAR(255)"/>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<sql>
DROP TRIGGER IF EXISTS default_config_update_trigger ON default_config;
CREATE TRIGGER default_config_update_trigger BEFORE UPDATE ON default_config FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS default_config_insert_trigger ON default_config;
CREATE TRIGGER default_config_insert_trigger BEFORE INSERT ON default_config FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -1,35 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="default_feature_flag-table">
<createTable tableName="default_feature_flag">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="default_feature_flag_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="enabled" type="BOOLEAN">
<constraints nullable="false"/>
</column>
<column name="feature_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="feature_id" baseTableName="default_feature_flag" constraintName="fk_default_feature_flag_feature" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="feature" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS default_feature_flag_update_trigger ON default_feature_flag;
CREATE TRIGGER default_feature_flag_update_trigger BEFORE UPDATE ON default_feature_flag FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS default_feature_flag_insert_trigger ON default_feature_flag;
CREATE TRIGGER default_feature_flag_insert_trigger BEFORE INSERT ON default_feature_flag FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -1,39 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="default_feature_mode-table">
<createTable tableName="default_feature_mode">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="default_feature_mode_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="mode" type="VARCHAR(255)">
<constraints nullable="true"/>
</column>
<column name="enabled" type="BOOLEAN">
<constraints nullable="false"/>
</column>
<column name="feature_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="feature_id" baseTableName="default_feature_mode" constraintName="fk_default_feature_mode_feature" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="feature" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS default_feature_mode_update_trigger ON default_feature_mode;
CREATE TRIGGER default_feature_mode_update_trigger BEFORE UPDATE ON default_feature_mode FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS default_feature_mode_insert_trigger ON default_feature_mode;
CREATE TRIGGER default_feature_mode_insert_trigger BEFORE INSERT ON default_feature_mode FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -1,32 +0,0 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="default_posttarget-table">
<createTable tableName="default_posttarget">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="default_posttarget_pkey"/>
</column>
<column name="name" type="VARCHAR(255)">
<constraints nullable="true"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<sql>
DROP TRIGGER IF EXISTS default_posttarget_update_trigger ON default_posttarget;
CREATE TRIGGER default_posttarget_update_trigger BEFORE UPDATE ON default_posttarget FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS default_posttarget_insert_trigger ON default_posttarget;
CREATE TRIGGER default_posttarget_insert_trigger BEFORE INSERT ON default_posttarget FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -18,7 +18,7 @@
<column name="enabled" type="BOOLEAN">
<constraints nullable="false"/>
</column>
<column name="feature_mode_id" type="BIGINT">
<column name="feature_mode" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="feature_flag_id" type="BIGINT">
@@ -34,10 +34,9 @@
<createIndex indexName="idx_feature_mode_flag_server_mode" tableName="feature_mode">
<column name="server_id"/>
<column name="feature_flag_id"/>
<column name="feature_mode_id"/>
<column name="feature_mode"/>
</createIndex>
<addForeignKeyConstraint baseColumnNames="feature_flag_id" baseTableName="feature_mode" constraintName="fk_feature_mode_flag" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="feature_flag" validate="true"/>
<addForeignKeyConstraint baseColumnNames="feature_mode_id" baseTableName="feature_mode" constraintName="fk_feature_mode_mode" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="default_feature_mode" validate="true"/>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="feature_mode" constraintName="fk_feature_mode_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS feature_mode_update_trigger ON feature_mode;

View File

@@ -9,9 +9,7 @@
<include file="trigger_functions.xml" relativeToChangelogFile="true"/>
<include file="server.xml" relativeToChangelogFile="true"/>
<include file="channel.xml" relativeToChangelogFile="true"/>
<include file="default_post_target.xml" relativeToChangelogFile="true"/>
<include file="post_target.xml" relativeToChangelogFile="true"/>
<include file="default_config.xml" relativeToChangelogFile="true"/>
<include file="default_emote.xml" relativeToChangelogFile="true"/>
<include file="emote.xml" relativeToChangelogFile="true"/>
<include file="feature.xml" relativeToChangelogFile="true"/>
@@ -20,8 +18,6 @@
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="channel_group_type.xml" relativeToChangelogFile="true"/>
<include file="channel_group.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true" />
<include file="feature_flag.xml" relativeToChangelogFile="true"/>
<include file="feature_mode.xml" relativeToChangelogFile="true"/>
<include file="lock.xml" relativeToChangelogFile="true"/>

View File

@@ -1,64 +0,0 @@
package dev.sheldan.abstracto.core.listener;
import dev.sheldan.abstracto.core.listener.sync.entity.FeatureFlagListener;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureFlag;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class FeatureFlagListenerTest {
@InjectMocks
private FeatureFlagListener testUnit;
@Mock
private FeatureFlagManagementService service;
@Mock
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
@Mock
private DefaultFeatureFlag defaultFeatureFlag1;
@Mock
private DefaultFeatureFlag defaultFeatureFlag2;
@Mock
private AFeature aFeature1;
@Mock
private AFeature aFeature2;
@Mock
private AServer server;
@Mock
private AFeatureFlag aFeatureFlag;
private static final Long SERVER_ID = 8L;
@Test
public void testCreateMultipleOneAlreadyExisting() {
when(server.getId()).thenReturn(SERVER_ID);
when(defaultFeatureFlagManagementService.getAllDefaultFeatureFlags()).thenReturn(Arrays.asList(defaultFeatureFlag1, defaultFeatureFlag2));
when(defaultFeatureFlag1.getFeature()).thenReturn(aFeature1);
when(defaultFeatureFlag2.getFeature()).thenReturn(aFeature2);
when(defaultFeatureFlag2.isEnabled()).thenReturn(true);
when(service.featureFlagExists(aFeature1, server)).thenReturn(true);
when(service.featureFlagExists(aFeature2, server)).thenReturn(false);
when(service.createFeatureFlag(aFeature2, SERVER_ID, true)).thenReturn(aFeatureFlag);
testUnit.updateServerConfig(server);
}
}

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
@@ -64,7 +65,7 @@ public class FeatureModeServiceBeanTest {
private AFeatureFlag featureFlag;
@Mock
private DefaultFeatureMode defaultFeatureMode;
private FeatureModeProperty defaultFeatureMode;
@Mock
private FeatureConfig featureConfig;
@@ -86,7 +87,7 @@ public class FeatureModeServiceBeanTest {
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.empty());
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(Optional.of(featureFlag));
testUnit.enableFeatureModeForFeature(featureEnum, server, featureMode);
verify(featureModeManagementService, times(1)).createMode(featureFlag, featureMode, true);
}
@@ -123,7 +124,7 @@ public class FeatureModeServiceBeanTest {
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.empty());
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(Optional.of(featureFlag));
testUnit.disableFeatureModeForFeature(featureEnum, server, featureMode);
verify(featureModeManagementService, times(1)).createMode(featureFlag, featureMode, false);
}
@@ -145,7 +146,7 @@ public class FeatureModeServiceBeanTest {
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
when(featureModeManagementService.doesFeatureModeExist(feature, server, featureMode)).thenReturn(false);
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
when(defaultFeatureMode.isEnabled()).thenReturn(true);
when(defaultFeatureMode.getEnabled()).thenReturn(true);
boolean actualResult = testUnit.featureModeActive(featureEnum, server, featureMode);
Assert.assertTrue(actualResult);
}
@@ -181,14 +182,13 @@ public class FeatureModeServiceBeanTest {
@Test
public void testEffectiveFeatureModesOnlyOneDefault() {
when(defaultFeatureMode.getFeature()).thenReturn(feature);
when(defaultFeatureMode.isEnabled()).thenReturn(true);
when(defaultFeatureMode.getFeature()).thenReturn(feature);
when(defaultFeatureMode.getEnabled()).thenReturn(true);
when(defaultFeatureMode.getFeatureName()).thenReturn(FEATURE_NAME);
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode));
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
when(featureConfigService.getFeatureDisplayForFeature(FEATURE_NAME)).thenReturn(featureConfig);
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(new ArrayList<>());
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
when(featureFlagManagementService.getFeatureFlag(FEATURE_NAME, server)).thenReturn(Optional.of(featureFlag));
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
Assert.assertEquals(1, effectiveFeatureModes.size());
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
@@ -196,7 +196,7 @@ public class FeatureModeServiceBeanTest {
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(FEATURE_MODE, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
}
@@ -205,10 +205,11 @@ public class FeatureModeServiceBeanTest {
when(aFeatureMode.getEnabled()).thenReturn(true);
when(aFeatureMode.getFeatureFlag()).thenReturn(featureFlag);
when(aFeatureMode.getServer()).thenReturn(server);
when(aFeatureMode.getFeatureMode()).thenReturn(defaultFeatureMode);
when(aFeatureMode.getFeatureMode()).thenReturn(FEATURE_MODE);
when(featureFlag.getFeature()).thenReturn(feature);
when(feature.getKey()).thenReturn(FEATURE_NAME);
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode));
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
when(featureConfigService.getFeatureDisplayForFeature(FEATURE_NAME)).thenReturn(featureConfig);
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(Arrays.asList(aFeatureMode));
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
@@ -218,7 +219,7 @@ public class FeatureModeServiceBeanTest {
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(FEATURE_MODE, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
}
@@ -227,48 +228,51 @@ public class FeatureModeServiceBeanTest {
when(aFeatureMode.getEnabled()).thenReturn(true);
when(aFeatureMode.getFeatureFlag()).thenReturn(featureFlag);
when(aFeatureMode.getServer()).thenReturn(server);
when(aFeatureMode.getFeatureMode()).thenReturn(defaultFeatureMode);
when(aFeatureMode.getFeatureMode()).thenReturn(FEATURE_MODE);
when(featureFlag.getFeature()).thenReturn(feature);
DefaultFeatureMode defaultFeatureMode2 = Mockito.mock(DefaultFeatureMode.class);
when(defaultFeatureMode2.getMode()).thenReturn("SECOND");
when(defaultFeatureMode2.getFeature()).thenReturn(feature);
when(defaultFeatureMode2.isEnabled()).thenReturn(false);
when(feature.getKey()).thenReturn(FEATURE_NAME);
FeatureModeProperty defaultFeatureMode2 = Mockito.mock(FeatureModeProperty.class);
String secondMode = "SECOND";
when(defaultFeatureMode2.getMode()).thenReturn(secondMode);
String feature2 = "FEATURE2";
when(defaultFeatureMode2.getFeatureName()).thenReturn(feature2);
when(defaultFeatureMode2.getEnabled()).thenReturn(false);
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode2, defaultFeatureMode));
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
when(featureConfigService.getFeatureDisplayForFeature(FEATURE_NAME)).thenReturn(featureConfig);
when(featureConfigService.getFeatureDisplayForFeature(feature2)).thenReturn(featureConfig);
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(Arrays.asList(aFeatureMode));
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
when(featureFlagManagementService.getFeatureFlag(feature2, server)).thenReturn(Optional.of(featureFlag));
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
Assert.assertEquals(2, effectiveFeatureModes.size());
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
Assert.assertEquals(false, featureModeDisplay.getIsDefaultValue());
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
FeatureModeDisplay activeFeaturemodeDisplay = effectiveFeatureModes.get(0);
Assert.assertEquals(false, activeFeaturemodeDisplay.getIsDefaultValue());
Assert.assertTrue(activeFeaturemodeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, activeFeaturemodeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, activeFeaturemodeDisplay.getFeatureMode().getServer());
Assert.assertEquals(FEATURE_MODE, activeFeaturemodeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, activeFeaturemodeDisplay.getFeatureConfig());
FeatureModeDisplay featureModeDisplay2 = effectiveFeatureModes.get(1);
Assert.assertEquals(true, featureModeDisplay2.getIsDefaultValue());
Assert.assertFalse(featureModeDisplay2.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, featureModeDisplay2.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, featureModeDisplay2.getFeatureMode().getServer());
Assert.assertEquals(defaultFeatureMode2, featureModeDisplay2.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, featureModeDisplay2.getFeatureConfig());
FeatureModeDisplay defaultFeatureModeDisplay = effectiveFeatureModes.get(1);
Assert.assertEquals(true, defaultFeatureModeDisplay.getIsDefaultValue());
Assert.assertFalse(defaultFeatureModeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, defaultFeatureModeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, defaultFeatureModeDisplay.getFeatureMode().getServer());
Assert.assertEquals(secondMode, defaultFeatureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, defaultFeatureModeDisplay.getFeatureConfig());
}
@Test
public void testGetEffectiveFeatureModesForFeature() {
when(defaultFeatureMode.getFeature()).thenReturn(feature);
when(defaultFeatureMode.isEnabled()).thenReturn(true);
when(defaultFeatureMode.getFeature()).thenReturn(feature);
when(defaultFeatureMode.getEnabled()).thenReturn(true);
when(defaultFeatureMode.getFeatureName()).thenReturn(FEATURE_NAME);
when(defaultFeatureModeManagement.getFeatureModesForFeature(feature)).thenReturn(Arrays.asList(defaultFeatureMode));
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
when(featureConfigService.getFeatureDisplayForFeature(FEATURE_NAME)).thenReturn(featureConfig);
when(featureModeManagementService.getFeatureModesOfFeatureInServer(server, feature)).thenReturn(new ArrayList<>());
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
when(featureFlagManagementService.getFeatureFlag(FEATURE_NAME, server)).thenReturn(Optional.of(featureFlag));
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server, feature);
Assert.assertEquals(1, effectiveFeatureModes.size());
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
@@ -276,7 +280,7 @@ public class FeatureModeServiceBeanTest {
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(FEATURE_MODE, featureModeDisplay.getFeatureMode().getFeatureMode());
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
}
}

View File

@@ -1,9 +1,9 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
import dev.sheldan.abstracto.core.repository.DefaultFeatureModeRepository;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import org.junit.Assert;
import org.junit.Test;
@@ -12,10 +12,9 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -26,44 +25,54 @@ public class DefaultFeatureModeManagementBeanTest {
private DefaultFeatureModeManagementBean testUnit;
@Mock
private DefaultFeatureModeRepository defaultFeatureModeRepository;
@Mock
private FeatureConfigService featureConfigService;
private DefaultConfigProperties defaultConfigProperties;
@Mock
private AFeature feature;
@Mock
private DefaultFeatureMode defaultFeatureMode1;
private FeatureConfigService featureConfigService;
@Mock
private DefaultFeatureMode defaultFeatureMode2;
private FeatureModeProperty defaultFeatureMode1;
@Mock
private FeatureModeProperty defaultFeatureMode2;
private static final String MODE_NAME = "mode";
private static final String FEATURE_NAME = "feature";
@Mock
private HashMap<String, FeatureModeProperty> mockedMap;
@Test
public void getFeatureModesForFeature() {
List<DefaultFeatureMode> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
when(defaultFeatureModeRepository.findByFeature(feature)).thenReturn(defaultFeatureModes);
List<DefaultFeatureMode> featureModesForFeature = testUnit.getFeatureModesForFeature(feature);
when(defaultFeatureMode1.getFeatureName()).thenReturn(FEATURE_NAME);
when(defaultFeatureMode2.getFeatureName()).thenReturn(FEATURE_NAME);
when(feature.getKey()).thenReturn(FEATURE_NAME);
List<FeatureModeProperty> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
when(defaultConfigProperties.getFeatureModes()).thenReturn(mockedMap);
when(mockedMap.values()).thenReturn(defaultFeatureModes);
List<FeatureModeProperty> featureModesForFeature = testUnit.getFeatureModesForFeature(feature);
Assert.assertEquals(defaultFeatureModes.size(), featureModesForFeature.size());
Assert.assertEquals(defaultFeatureModes, featureModesForFeature);
}
@Test
public void testGetAll() {
List<DefaultFeatureMode> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
when(defaultFeatureModeRepository.findAll()).thenReturn(defaultFeatureModes);
List<DefaultFeatureMode> featureModesForFeature = testUnit.getAll();
List<FeatureModeProperty> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
when(defaultConfigProperties.getFeatureModes()).thenReturn(mockedMap);
when(mockedMap.values()).thenReturn(defaultFeatureModes);
List<FeatureModeProperty> featureModesForFeature = testUnit.getAll();
Assert.assertEquals(defaultFeatureModes.size(), featureModesForFeature.size());
Assert.assertEquals(defaultFeatureModes, featureModesForFeature);
}
@Test
public void getFeatureModeOptional() {
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.of(defaultFeatureMode1));
Optional<DefaultFeatureMode> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
when(defaultConfigProperties.getFeatureModes()).thenReturn(mockedMap);
when(mockedMap.get(MODE_NAME)).thenReturn(defaultFeatureMode1);
Optional<FeatureModeProperty> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
Assert.assertTrue(featureModeOptional.isPresent());
featureModeOptional.ifPresent(defaultFeatureMode ->
Assert.assertEquals(defaultFeatureMode1, defaultFeatureMode)
@@ -72,21 +81,22 @@ public class DefaultFeatureModeManagementBeanTest {
@Test
public void getFeatureModeOptionalNotExisting() {
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.empty());
Optional<DefaultFeatureMode> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
Optional<FeatureModeProperty> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
Assert.assertFalse(featureModeOptional.isPresent());
}
@Test
public void getFeatureMode() {
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.of(defaultFeatureMode1));
DefaultFeatureMode defaultFeatureMode = testUnit.getFeatureMode(feature, MODE_NAME);
when(defaultConfigProperties.getFeatureModes()).thenReturn(mockedMap);
when(mockedMap.get(MODE_NAME)).thenReturn(defaultFeatureMode1);
FeatureModeProperty defaultFeatureMode = testUnit.getFeatureMode(feature, MODE_NAME);
Assert.assertEquals(defaultFeatureMode1, defaultFeatureMode);
}
@Test(expected = FeatureModeNotFoundException.class)
public void getFeatureModeNotExisting() {
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.empty());
when(feature.getKey()).thenReturn(FEATURE_NAME);
when(featureConfigService.getFeatureModesFromFeatureAsString(FEATURE_NAME)).thenReturn(new ArrayList<>());
testUnit.getFeatureMode(feature, MODE_NAME);
}
}

View File

@@ -31,9 +31,6 @@ public class FeatureModeManagementServiceBeanTest {
@Mock
private AFeature feature;
@Mock
private DefaultFeatureMode defaultFeatureMode;
@Mock
private AFeatureFlag featureFlag;
@@ -51,12 +48,10 @@ public class FeatureModeManagementServiceBeanTest {
@Test
public void createModeWithModeAsString() {
when(featureFlag.getServer()).thenReturn(server);
when(featureFlag.getFeature()).thenReturn(feature);
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
AFeatureMode createdMode = testUnit.createMode(featureFlag, FEATURE_MODE, true);
Assert.assertEquals(true, createdMode.getEnabled());
Assert.assertEquals(featureFlag, createdMode.getFeatureFlag());
Assert.assertEquals(defaultFeatureMode, createdMode.getFeatureMode());
Assert.assertEquals(FEATURE_MODE, createdMode.getFeatureMode());
Assert.assertEquals(server, createdMode.getServer());
verify(featureModeRepository, times(1)).save(createdMode);
}
@@ -64,13 +59,11 @@ public class FeatureModeManagementServiceBeanTest {
@Test
public void testCreateMode() {
when(featureFlag.getServer()).thenReturn(server);
when(featureFlag.getFeature()).thenReturn(feature);
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
AFeatureMode createdMode = testUnit.createMode(featureFlag, featureMode, true);
Assert.assertEquals(true, createdMode.getEnabled());
Assert.assertEquals(featureFlag, createdMode.getFeatureFlag());
Assert.assertEquals(defaultFeatureMode, createdMode.getFeatureMode());
Assert.assertEquals(FEATURE_MODE, createdMode.getFeatureMode());
Assert.assertEquals(server, createdMode.getServer());
verify(featureModeRepository, times(1)).save(createdMode);
}
@@ -79,7 +72,7 @@ public class FeatureModeManagementServiceBeanTest {
public void featureModeActive() {
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
when(aFeatureMode.getEnabled()).thenReturn(true);
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
Assert.assertTrue(testUnit.isFeatureModeActive(feature, server, featureMode));
}
@@ -87,40 +80,40 @@ public class FeatureModeManagementServiceBeanTest {
public void featureModeNotActive() {
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
when(aFeatureMode.getEnabled()).thenReturn(false);
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
Assert.assertFalse(testUnit.isFeatureModeActive(feature, server, featureMode));
}
@Test
public void featureModeNotPresent() {
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
Assert.assertFalse(testUnit.isFeatureModeActive(feature, server, featureMode));
}
@Test
public void featureModeStringExists() {
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
Assert.assertTrue(testUnit.doesFeatureModeExist(feature, server, FEATURE_MODE));
}
@Test
public void featureModeObjectExists() {
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
Assert.assertTrue(testUnit.doesFeatureModeExist(feature, server, featureMode));
}
@Test
public void featureModeDoesNotExist() {
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
Assert.assertFalse(testUnit.doesFeatureModeExist(feature, server, featureMode));
}
@Test
public void testGetFeatureModeOptional() {
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
Optional<AFeatureMode> featureModeOptional = testUnit.getFeatureMode(feature, server, FEATURE_MODE);
Assert.assertTrue(featureModeOptional.isPresent());
featureModeOptional.ifPresent(aFeatureMode1 ->
@@ -130,7 +123,7 @@ public class FeatureModeManagementServiceBeanTest {
@Test
public void testGetFeatureModeOptionalNotExisting() {
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
Optional<AFeatureMode> featureModeOptional = testUnit.getFeatureMode(feature, server, FEATURE_MODE);
Assert.assertFalse(featureModeOptional.isPresent());
}

View File

@@ -1,55 +0,0 @@
package dev.sheldan.abstracto.core.models.database;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
@Entity
@Table(name="default_config")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class ADefaultConfig implements Serializable {
@javax.persistence.Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String name;
@Column(name = "string_value")
@Setter
private String stringValue;
@Column(name = "double_value")
@Setter
private Double doubleValue;
@Column(name = "long_value")
@Setter
private Long longValue;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
public String getValueAsString() {
if(getLongValue() != null) {
return getLongValue().toString();
} else if(getDoubleValue() != null) {
return getDoubleValue().toString();
} else if(getStringValue() != null) {
return getStringValue();
}
return null;
}
}

View File

@@ -27,9 +27,8 @@ public class AFeatureMode implements Serializable {
@JoinColumn(name = "feature_flag_id", nullable = false)
private AFeatureFlag featureFlag;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "feature_mode_id", nullable = false)
private DefaultFeatureMode featureMode;
@Column(name = "feature_mode")
private String featureMode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "server_id", nullable = false)

View File

@@ -1,44 +0,0 @@
package dev.sheldan.abstracto.core.models.database;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
@Entity
@Table(name="default_feature_flag")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DefaultFeatureFlag implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
@Column(name = "id")
public Long id;
@Getter
@Setter
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "feature_id", nullable = false)
private AFeature feature;
@Getter
@Setter
@Column(name = "enabled")
private boolean enabled;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -1,55 +0,0 @@
package dev.sheldan.abstracto.core.models.database;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
import java.util.List;
@Entity
@Table(name="default_feature_mode")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DefaultFeatureMode implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
@Column(name = "id")
public Long id;
@Getter
@Setter
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "feature_id", nullable = false)
private AFeature feature;
@Getter
@Setter
@OneToMany(fetch = FetchType.LAZY, mappedBy = "featureMode")
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private List<AFeatureMode> modes;
@Getter
@Setter
@Column(name = "enabled")
private boolean enabled;
@Getter
@Setter
@Column(name = "mode")
private String mode;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -1,36 +0,0 @@
package dev.sheldan.abstracto.core.models.database;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
@Entity
@Table(name="default_posttarget")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DefaultPostTarget implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
@Column(name = "id")
private Long id;
@Getter
@Column(name = "name")
private String name;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.models.property;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FeatureFlagProperty {
private String featureName;
private Boolean enabled;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.models.property;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FeatureModeProperty {
private String featureName;
private String mode;
private Boolean enabled;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.models.property;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PostTargetProperty {
private String name;
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.core.models.property;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class SystemConfigProperty {
private String name;
private Long longValue;
private String stringValue;
private Double doubleValue;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.models.template.commands;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class DefaultFeatureFlagDisplay {
private FeatureFlagProperty featureFlagProperty;
private FeatureConfig featureConfig;
}

View File

@@ -12,4 +12,5 @@ import java.util.List;
@Setter
public class FeaturesModel extends UserInitiatedServerContext {
private List<FeatureFlagDisplay> features;
private List<DefaultFeatureFlagDisplay> defaultFeatures;
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.core.models.template.commands;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -10,5 +10,5 @@ import lombok.Setter;
@Builder
public class SetupSystemConfigMessageModel {
private String configKey;
private ADefaultConfig defaultConfig;
private SystemConfigProperty defaultConfig;
}

View File

@@ -12,6 +12,8 @@ public interface FeatureFlagService {
void enableFeature(FeatureConfig name, AServer server);
void disableFeature(FeatureConfig name, Long serverId);
void disableFeature(FeatureConfig name, AServer server);
AFeatureFlag createInstanceFromDefaultConfig(FeatureEnum name, Long serverId);
AFeatureFlag createInstanceFromDefaultConfig(FeatureEnum name, AServer server);
boolean getFeatureFlagValue(FeatureEnum key, Long serverId);
boolean getFeatureFlagValue(FeatureEnum key, AServer server);
AFeatureFlag updateFeatureFlag(FeatureEnum key, Long serverId, Boolean newValue);

View File

@@ -1,10 +1,7 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.ADefaultConfig;
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
public interface DefaultConfigManagementService {
void createDefaultConfig(String key, String value);
void createDefaultConfig(String key, Long value);
void createDefaultConfig(String key, Double value);
ADefaultConfig getDefaultConfig(String key);
SystemConfigProperty getDefaultConfig(String key);
}

View File

@@ -1,10 +1,14 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureFlag;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.property.FeatureFlagProperty;
import java.util.List;
public interface DefaultFeatureFlagManagementService {
List<String> getDefaultFeatureKeys();
List<DefaultFeatureFlag> getAllDefaultFeatureFlags();
FeatureFlagProperty getDefaultFeatureFlagProperty(AFeature feature);
FeatureFlagProperty getDefaultFeatureFlagProperty(FeatureEnum feature);
List<FeatureFlagProperty> getAllDefaultFeatureFlags();
}

View File

@@ -1,14 +1,14 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.AFeature;
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
import dev.sheldan.abstracto.core.models.property.FeatureModeProperty;
import java.util.List;
import java.util.Optional;
public interface DefaultFeatureModeManagement {
List<DefaultFeatureMode> getFeatureModesForFeature(AFeature feature);
List<DefaultFeatureMode> getAll();
Optional<DefaultFeatureMode> getFeatureModeOptional(AFeature feature, String mode);
DefaultFeatureMode getFeatureMode(AFeature feature, String mode);
List<FeatureModeProperty> getFeatureModesForFeature(AFeature feature);
List<FeatureModeProperty> getAll();
Optional<FeatureModeProperty> getFeatureModeOptional(AFeature feature, String mode);
FeatureModeProperty getFeatureMode(AFeature feature, String mode);
}

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.DefaultPostTarget;
import dev.sheldan.abstracto.core.models.property.PostTargetProperty;
import java.util.List;
public interface DefaultPostTargetManagementService {
List<DefaultPostTarget> getAllDefaultPostTargets();
List<PostTargetProperty> getAllDefaultPostTargets();
List<String> getDefaultPostTargetKeys();
}

View File

@@ -5,13 +5,16 @@ import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import java.util.List;
import java.util.Optional;
public interface FeatureFlagManagementService {
AFeatureFlag createFeatureFlag(AFeature feature, Long serverId, Boolean newValue);
AFeatureFlag createFeatureFlag(AFeature feature, AServer server, Boolean newValue);
AFeatureFlag getFeatureFlag(AFeature key, Long serverId);
Optional<AFeatureFlag> getFeatureFlag(AFeature feature, Long serverId);
Optional<AFeatureFlag> getFeatureFlag(String featureKey, Long serverId);
Optional<AFeatureFlag> getFeatureFlag(String featureKey, AServer server);
boolean featureFlagExists(AFeature feature, AServer server);
AFeatureFlag getFeatureFlag(AFeature key, AServer server);
Optional<AFeatureFlag> getFeatureFlag(AFeature feature, AServer server);
List<AFeatureFlag> getFeatureFlagsOfServer(AServer server);
AFeatureFlag setFeatureFlagValue(AFeature feature, Long serverId, Boolean newValue);
AFeatureFlag setFeatureFlagValue(AFeature feature, AServer server, Boolean newValue);

View File

@@ -104,10 +104,10 @@ Enforce the role restrictions of commands::
* Description: Causes the role restrictions for a all commands in the `feature`/the `command` to be in effect again.
Enabling a feature mode::
* Usage: `enableMode <featureName> <mode>`
* Description: Enables the mode `mode` in feature `featureName`.
* Description: Enables the mode `mode` in feature `featureName`. If the enabled state of the feature `featureName` is part of the default config, it will no longer be default config that after executing `enableMode`.
Disabling a feature mode::
* Usage: `disableMode <featureName> <mode>`
* Description: Disables the mode `mode` in feature `featureName`.
* Description: Disables the mode `mode` in feature `featureName`. If the enabled state of the feature `featureName` is part of the default config, it will no longer be default config after executing `disableMode`.
Listing all feature modes::
* usage `featureModes [feature]`
* Description: Lists all of the currently available feature modes and the feature they are associated with. If `feature` is given, it only lists the feature modes of this feature. The output also includes whether or not the current mode is enabled and if this value comes from the default configuration.

View File

@@ -6,7 +6,7 @@ This component will contain multiple features, currently only emote tracking is
This feature is about tracking the usage of emotes from the server and external servers.
The intention of this feature is to see what emotes are doing better than others and which emotes might be interesting to add to the server.
Feature key: `emote_tracking`
Feature key: `emoteTracking`
==== Feature modes
`emoteAutoTrack`:: If this is enabled, emotes which are created within the server, are automatically stored and tracked. If they are renamed/deleted this will also be reflected automatically. Enabled by default.

View File

@@ -118,7 +118,7 @@ This feature enables the automatic embedding of messages containing a message li
If a message contains a link to a discord message this will create an embed containing the the message content. This supports image attachments, but not videos or files.
A reaction is placed on the embedded message which can be used to delete this embed. Only the original author and the person creating the embed can delete the embed this way.
Feature key: `link_embeds`
Feature key: `linkEmbeds`
=== Repost detection and tracking