Add documentation and local build Dockerfile
- README.md: Build and deployment guide for beginners - Extend-Function.md: Extended files list and version upgrade guide - Unlock-License.md: License check removal documentation - Dockerfile.local: Local source build support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7ce2e2b810
commit
7e5c7b8c36
29
Dockerfile.local
Normal file
29
Dockerfile.local
Normal file
@ -0,0 +1,29 @@
|
||||
FROM rockylinux:9 AS builder
|
||||
|
||||
# Install build dependencies
|
||||
RUN dnf install -y git golang make gcc
|
||||
|
||||
# Copy local source
|
||||
WORKDIR /build
|
||||
COPY . .
|
||||
|
||||
# Build
|
||||
RUN go build -v -mod=vendor -o mattermost ./cmd/mattermost
|
||||
|
||||
# Runtime image
|
||||
FROM rockylinux:9-minimal
|
||||
|
||||
RUN microdnf install -y ca-certificates tzdata && microdnf clean all
|
||||
|
||||
WORKDIR /mattermost
|
||||
COPY --from=builder /build/mattermost /mattermost/bin/mattermost
|
||||
COPY --from=builder /build/config /mattermost/config
|
||||
COPY --from=builder /build/i18n /mattermost/i18n
|
||||
COPY --from=builder /build/fonts /mattermost/fonts
|
||||
COPY --from=builder /build/templates /mattermost/templates
|
||||
COPY --from=builder /build/client /mattermost/client
|
||||
|
||||
RUN mkdir -p /mattermost/data /mattermost/logs /mattermost/plugins /mattermost/client/plugins
|
||||
|
||||
EXPOSE 8065
|
||||
ENTRYPOINT ["/mattermost/bin/mattermost"]
|
||||
325
Extend-Function.md
Normal file
325
Extend-Function.md
Normal file
@ -0,0 +1,325 @@
|
||||
# Mattermost Community Enterprise - 확장 기능 문서
|
||||
|
||||
이 문서는 Team Edition에서 Enterprise 기능을 활성화하기 위해 생성/수정된 파일과 버전 업그레이드 시 이식해야 할 내용을 정리합니다.
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
```
|
||||
mattermost-community-enterprise/
|
||||
├── enterprise/ # Enterprise 브릿지 (기존)
|
||||
│ └── community_imports.go # enterprise-community 임포트
|
||||
├── enterprise-impl/ # [신규] Enterprise 구현체
|
||||
│ ├── enterprise.go # 메인 등록 파일
|
||||
│ ├── go.mod # 별도 모듈 정의
|
||||
│ ├── go.sum
|
||||
│ ├── ldap/ # LDAP 구현
|
||||
│ ├── saml/ # SAML 구현
|
||||
│ ├── cluster/ # 클러스터링 구현
|
||||
│ ├── metrics/ # Prometheus 메트릭 구현
|
||||
│ ├── compliance/ # 컴플라이언스 구현
|
||||
│ ├── data_retention/ # 데이터 보존 구현
|
||||
│ ├── message_export/ # 메시지 내보내기 구현
|
||||
│ ├── account_migration/ # 계정 마이그레이션 구현
|
||||
│ ├── access_control/ # 접근 제어 구현
|
||||
│ ├── ip_filtering/ # IP 필터링 구현
|
||||
│ ├── notification/ # 알림 구현
|
||||
│ ├── oauthproviders/ # OAuth 프로바이더 구현
|
||||
│ ├── outgoing_oauth_connection/ # 외부 OAuth 연결 구현
|
||||
│ ├── push_proxy/ # 푸시 프록시 구현
|
||||
│ └── searchengine/ # 검색 엔진 구현
|
||||
├── enterprise-community/ # [신규] Enterprise 등록 파일
|
||||
│ ├── imports.go # 모든 구현체 임포트
|
||||
│ ├── ldap/init.go
|
||||
│ ├── saml/init.go
|
||||
│ ├── cluster/init.go
|
||||
│ ├── metrics/init.go
|
||||
│ ├── compliance/init.go
|
||||
│ ├── data_retention/init.go
|
||||
│ ├── message_export/init.go
|
||||
│ ├── account_migration/init.go
|
||||
│ ├── access_control/init.go
|
||||
│ ├── ip_filtering/init.go
|
||||
│ ├── notification/init.go
|
||||
│ ├── outgoing_oauth_connection/init.go
|
||||
│ ├── push_proxy/init.go
|
||||
│ └── searchengine/init.go
|
||||
├── channels/api4/ # [수정됨] API 라이선스 체크 제거
|
||||
│ ├── ldap.go
|
||||
│ ├── saml.go
|
||||
│ ├── user.go
|
||||
│ ├── group.go
|
||||
│ └── scheme.go
|
||||
├── channels/app/platform/ # [수정됨] 메트릭 핸들러
|
||||
│ └── metrics.go
|
||||
├── Dockerfile.local # [신규] 로컬 빌드용 Dockerfile
|
||||
├── Dockerfile.mattermost # [신규] Git 빌드용 Dockerfile
|
||||
├── README.md # [신규] 빌드 가이드
|
||||
├── Extend-Function.md # [신규] 이 문서
|
||||
└── Unlock-License.md # [신규] 라이선스 해제 문서
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 생성된 파일 상세
|
||||
|
||||
### 1. enterprise-impl/ (Enterprise 구현체)
|
||||
|
||||
#### enterprise-impl/enterprise.go
|
||||
|
||||
Enterprise 기능 등록을 위한 메인 파일입니다.
|
||||
|
||||
```go
|
||||
package enterprise
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost/server/v8/channels/app"
|
||||
"github.com/mattermost/mattermost/server/v8/enterprise-impl/ldap"
|
||||
"github.com/mattermost/mattermost/server/v8/enterprise-impl/cluster"
|
||||
"github.com/mattermost/mattermost/server/v8/enterprise-impl/metrics"
|
||||
// ... 기타 imports
|
||||
)
|
||||
|
||||
func init() {
|
||||
app.RegisterLdapInterface(ldap.New)
|
||||
app.RegisterClusterInterface(cluster.New)
|
||||
app.RegisterMetricsInterface(metrics.New)
|
||||
// ... 기타 등록
|
||||
}
|
||||
```
|
||||
|
||||
#### enterprise-impl/ldap/ldap.go
|
||||
|
||||
LDAP 인증 및 동기화 구현체입니다.
|
||||
|
||||
주요 메서드:
|
||||
- `DoLogin()` - LDAP 로그인 처리
|
||||
- `GetUser()` - LDAP에서 사용자 조회
|
||||
- `GetGroup()` - LDAP에서 그룹 조회
|
||||
- `SyncAllUsers()` - 모든 사용자 동기화
|
||||
- `RunTest()` - LDAP 연결 테스트
|
||||
|
||||
#### enterprise-impl/cluster/cluster.go
|
||||
|
||||
Redis 기반 클러스터링 구현체입니다.
|
||||
|
||||
주요 메서드:
|
||||
- `StartInterNodeCommunication()` - 노드 간 통신 시작
|
||||
- `RegisterClusterMessageHandler()` - 메시지 핸들러 등록
|
||||
- `SendClusterMessage()` - 클러스터 메시지 전송
|
||||
- `GetClusterStats()` - 클러스터 상태 조회
|
||||
|
||||
#### enterprise-impl/metrics/metrics.go
|
||||
|
||||
Prometheus 메트릭 수집 구현체입니다.
|
||||
|
||||
주요 메서드:
|
||||
- `Register()` - 메트릭 등록
|
||||
- `Handler()` - HTTP 핸들러 반환
|
||||
- `IncrementHTTPRequest()` - HTTP 요청 카운트
|
||||
- `ObserveAPIEndpointDuration()` - API 응답 시간 측정
|
||||
|
||||
### 2. enterprise-community/ (등록 파일)
|
||||
|
||||
#### enterprise-community/imports.go
|
||||
|
||||
모든 Enterprise 구현체를 임포트하여 init()이 실행되도록 합니다.
|
||||
|
||||
```go
|
||||
package enterprise_community
|
||||
|
||||
import (
|
||||
_ "github.com/mattermost/mattermost/server/v8/enterprise-community/ldap"
|
||||
_ "github.com/mattermost/mattermost/server/v8/enterprise-community/cluster"
|
||||
_ "github.com/mattermost/mattermost/server/v8/enterprise-community/metrics"
|
||||
// ... 기타 imports
|
||||
)
|
||||
```
|
||||
|
||||
#### enterprise-community/ldap/init.go
|
||||
|
||||
LDAP 구현체를 app에 등록합니다.
|
||||
|
||||
```go
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost/server/v8/channels/app"
|
||||
ldapImpl "github.com/mattermost/mattermost/server/v8/enterprise-impl/ldap"
|
||||
)
|
||||
|
||||
func init() {
|
||||
app.RegisterLdapInterface(ldapImpl.New)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 수정된 파일
|
||||
|
||||
#### channels/api4/ldap.go
|
||||
|
||||
LDAP 관련 API에서 라이선스 체크 제거:
|
||||
- `syncLdap()` - LDAP 동기화
|
||||
- `testLdap()` - LDAP 연결 테스트
|
||||
- `getLdapGroups()` - LDAP 그룹 조회
|
||||
- `linkLdapGroup()` - LDAP 그룹 연결
|
||||
- `unlinkLdapGroup()` - LDAP 그룹 연결 해제
|
||||
- `migrateIdLdap()` - LDAP ID 마이그레이션
|
||||
- `createLdapPublicCertificate()` - 인증서 생성
|
||||
|
||||
#### channels/api4/scheme.go
|
||||
|
||||
커스텀 권한 스키마 API에서 라이선스 체크 제거:
|
||||
- `createScheme()` - 스키마 생성
|
||||
- `patchScheme()` - 스키마 수정
|
||||
- `deleteScheme()` - 스키마 삭제
|
||||
|
||||
#### channels/api4/group.go
|
||||
|
||||
그룹 관련 API에서 라이선스 체크 제거:
|
||||
- `getGroupsByTeam()` - 팀별 그룹 조회
|
||||
- `getGroupsByChannel()` - 채널별 그룹 조회
|
||||
|
||||
#### channels/api4/user.go
|
||||
|
||||
사용자 마이그레이션 API에서 라이선스 체크 제거:
|
||||
- `migrateAuthToLdap()` - LDAP 인증 마이그레이션
|
||||
- `migrateAuthToSaml()` - SAML 인증 마이그레이션
|
||||
|
||||
#### channels/app/platform/metrics.go
|
||||
|
||||
메트릭 라우터에 `/metrics` 핸들러 등록 추가:
|
||||
|
||||
```go
|
||||
// MetricsHandlerProvider 인터페이스 추가
|
||||
type MetricsHandlerProvider interface {
|
||||
Handler() http.Handler
|
||||
}
|
||||
|
||||
// initMetricsRouter()에 핸들러 등록 코드 추가
|
||||
if pm.metricsImpl != nil {
|
||||
if handlerProvider, ok := pm.metricsImpl.(MetricsHandlerProvider); ok {
|
||||
pm.router.Handle("/metrics", handlerProvider.Handler())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 버전 업그레이드 가이드
|
||||
|
||||
Mattermost 새 버전으로 업그레이드할 때 다음 파일들을 이식해야 합니다.
|
||||
|
||||
### 필수 이식 파일
|
||||
|
||||
1. **enterprise-impl/ 전체 디렉토리**
|
||||
- 새 버전의 einterfaces에 맞게 수정 필요
|
||||
- 인터페이스 변경 시 구현체 업데이트
|
||||
|
||||
2. **enterprise-community/ 전체 디렉토리**
|
||||
- 새로운 Enterprise 기능 추가 시 init 파일 추가
|
||||
- app 패키지 경로 변경 시 import 수정
|
||||
|
||||
3. **enterprise/community_imports.go**
|
||||
- enterprise-community 패키지 임포트 유지
|
||||
|
||||
### API 라이선스 체크 재제거
|
||||
|
||||
새 버전에서 다음 파일들의 라이선스 체크를 다시 제거해야 합니다:
|
||||
|
||||
1. **channels/api4/ldap.go**
|
||||
- `c.App.Channels().License() == nil` 조건문 찾아서 제거
|
||||
- `!*c.App.Channels().License().Features.LDAP` 조건 제거
|
||||
|
||||
2. **channels/api4/scheme.go**
|
||||
- `!*c.App.Channels().License().Features.CustomPermissionsSchemes` 조건 제거
|
||||
|
||||
3. **channels/api4/group.go**
|
||||
- `!*c.App.Channels().License().Features.LDAPGroups` 조건 제거
|
||||
|
||||
4. **channels/api4/user.go**
|
||||
- LDAP/SAML 마이그레이션 라이선스 체크 제거
|
||||
|
||||
5. **channels/app/platform/metrics.go**
|
||||
- `MetricsHandlerProvider` 인터페이스 추가
|
||||
- `/metrics` 핸들러 등록 코드 추가
|
||||
|
||||
### 이식 스크립트 예시
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# upgrade-mattermost.sh
|
||||
|
||||
NEW_VERSION=$1
|
||||
OLD_DIR="mattermost-community-enterprise"
|
||||
NEW_DIR="mattermost-server-$NEW_VERSION"
|
||||
|
||||
# 1. 새 버전 다운로드
|
||||
git clone https://github.com/mattermost/mattermost.git $NEW_DIR
|
||||
cd $NEW_DIR/server
|
||||
|
||||
# 2. Enterprise 구현체 복사
|
||||
cp -r $OLD_DIR/enterprise-impl ./
|
||||
cp -r $OLD_DIR/enterprise-community ./
|
||||
|
||||
# 3. community_imports.go 복사
|
||||
cp $OLD_DIR/enterprise/community_imports.go ./enterprise/
|
||||
|
||||
# 4. go.mod 업데이트 (enterprise-impl 추가)
|
||||
echo 'replace github.com/mattermost/mattermost/server/v8/enterprise-impl => ./enterprise-impl' >> go.mod
|
||||
|
||||
# 5. vendor 업데이트
|
||||
go mod vendor
|
||||
|
||||
echo "이제 API 파일에서 라이선스 체크를 수동으로 제거하세요"
|
||||
```
|
||||
|
||||
### 라이선스 체크 자동 제거 스크립트
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# remove-license-checks.sh
|
||||
|
||||
# LDAP 라이선스 체크 제거
|
||||
sed -i '/c\.App\.Channels()\.License() == nil.*LDAP/d' channels/api4/ldap.go
|
||||
sed -i '/!.*License()\.Features\.LDAP/d' channels/api4/ldap.go
|
||||
|
||||
# Scheme 라이선스 체크 제거
|
||||
sed -i '/License()\.Features\.CustomPermissionsSchemes/d' channels/api4/scheme.go
|
||||
|
||||
# Group 라이선스 체크 제거
|
||||
sed -i '/License()\.Features\.LDAPGroups/d' channels/api4/group.go
|
||||
|
||||
echo "라이선스 체크 제거 완료. 빌드 테스트를 실행하세요."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## einterfaces 매핑
|
||||
|
||||
| 인터페이스 | 구현 파일 | 등록 함수 |
|
||||
|-----------|----------|----------|
|
||||
| LdapInterface | enterprise-impl/ldap/ldap.go | app.RegisterLdapInterface |
|
||||
| SamlInterface | enterprise-impl/saml/saml.go | app.RegisterSamlInterface |
|
||||
| ClusterInterface | enterprise-impl/cluster/cluster.go | app.RegisterClusterInterface |
|
||||
| MetricsInterface | enterprise-impl/metrics/metrics.go | app.RegisterMetricsInterface |
|
||||
| ComplianceInterface | enterprise-impl/compliance/compliance.go | app.RegisterComplianceInterface |
|
||||
| DataRetentionInterface | enterprise-impl/data_retention/data_retention.go | app.RegisterDataRetentionInterface |
|
||||
| MessageExportInterface | enterprise-impl/message_export/message_export.go | app.RegisterMessageExportInterface |
|
||||
| AccountMigrationInterface | enterprise-impl/account_migration/account_migration.go | app.RegisterAccountMigrationInterface |
|
||||
|
||||
---
|
||||
|
||||
## 주의사항
|
||||
|
||||
1. **UI 라이선스 체크**: 웹 클라이언트(client/ 디렉토리)에도 라이선스 체크가 있을 수 있습니다. JavaScript 파일은 minified 상태라 수정이 어렵습니다.
|
||||
|
||||
2. **버전 호환성**: 이 구현체는 Mattermost v9.x를 기준으로 작성되었습니다. 메이저 버전이 변경되면 인터페이스 시그니처가 달라질 수 있습니다.
|
||||
|
||||
3. **테스트**: 업그레이드 후 반드시 모든 Enterprise 기능을 테스트하세요:
|
||||
- LDAP 로그인
|
||||
- 클러스터 동기화
|
||||
- Prometheus 메트릭 (/metrics 엔드포인트)
|
||||
- 커스텀 권한 스키마 생성/수정
|
||||
|
||||
4. **상용 사용**: 이 프로젝트는 학습 및 개인 사용 목적입니다. 상용 환경에서는 Mattermost 공식 라이선스를 구매하세요.
|
||||
328
README.md
Normal file
328
README.md
Normal file
@ -0,0 +1,328 @@
|
||||
# Mattermost Community Enterprise
|
||||
|
||||
라이선스 없이 Enterprise 기능을 사용할 수 있는 Mattermost 오픈소스 빌드입니다.
|
||||
|
||||
## 시스템 요구사항
|
||||
|
||||
- **OS**: Rocky Linux 9 / CentOS 9 / RHEL 9 (권장) 또는 Ubuntu 22.04+
|
||||
- **CPU**: 최소 2 Core
|
||||
- **RAM**: 최소 2GB (권장 4GB)
|
||||
- **디스크**: 최소 20GB
|
||||
- **네트워크**: 인터넷 연결 필요 (빌드 시)
|
||||
|
||||
## 빠른 시작 (Docker 사용)
|
||||
|
||||
### 1. 소스 코드 받기
|
||||
|
||||
```bash
|
||||
git clone http://10.0.4.213:3000/claude/mattermost-community-enterprise.git
|
||||
cd mattermost-community-enterprise
|
||||
```
|
||||
|
||||
### 2. Docker 이미지 빌드
|
||||
|
||||
```bash
|
||||
# 로컬 소스로 빌드 (권장)
|
||||
docker build -f Dockerfile.local -t mattermost-community:latest .
|
||||
|
||||
# 또는 Git에서 직접 빌드 (네트워크 필요)
|
||||
docker build -f Dockerfile.mattermost -t mattermost-community:latest .
|
||||
```
|
||||
|
||||
### 3. Docker Compose로 실행
|
||||
|
||||
```bash
|
||||
# docker-compose.yml 파일 생성 (아래 내용 참고)
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**docker-compose.yml 예시:**
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
environment:
|
||||
POSTGRES_DB: mattermost
|
||||
POSTGRES_USER: mmuser
|
||||
POSTGRES_PASSWORD: mmpassword
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
mattermost:
|
||||
image: mattermost-community:latest
|
||||
depends_on:
|
||||
- postgres
|
||||
ports:
|
||||
- "8065:8065"
|
||||
environment:
|
||||
MM_SQLSETTINGS_DRIVERNAME: postgres
|
||||
MM_SQLSETTINGS_DATASOURCE: postgres://mmuser:mmpassword@postgres:5432/mattermost?sslmode=disable
|
||||
volumes:
|
||||
- mattermost_data:/mattermost/data
|
||||
- mattermost_logs:/mattermost/logs
|
||||
- mattermost_plugins:/mattermost/plugins
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
mattermost_data:
|
||||
mattermost_logs:
|
||||
mattermost_plugins:
|
||||
```
|
||||
|
||||
### 4. 접속
|
||||
|
||||
브라우저에서 `http://서버IP:8065` 로 접속합니다.
|
||||
|
||||
---
|
||||
|
||||
## 수동 빌드 (Docker 없이)
|
||||
|
||||
### 1. 의존성 설치
|
||||
|
||||
**Rocky Linux / CentOS 9:**
|
||||
|
||||
```bash
|
||||
sudo dnf install -y git golang make gcc
|
||||
```
|
||||
|
||||
**Ubuntu 22.04:**
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y git golang-go make gcc
|
||||
```
|
||||
|
||||
### 2. Go 버전 확인
|
||||
|
||||
Go 1.21 이상이 필요합니다.
|
||||
|
||||
```bash
|
||||
go version
|
||||
# go version go1.21.x linux/amd64
|
||||
```
|
||||
|
||||
Go 버전이 낮으면 최신 버전을 설치합니다:
|
||||
|
||||
```bash
|
||||
# Rocky Linux
|
||||
sudo dnf module enable go-toolset:rhel9
|
||||
sudo dnf install -y go-toolset
|
||||
|
||||
# 또는 직접 설치
|
||||
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
|
||||
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
|
||||
export PATH=$PATH:/usr/local/go/bin
|
||||
```
|
||||
|
||||
### 3. 소스 코드 받기
|
||||
|
||||
```bash
|
||||
git clone http://10.0.4.213:3000/claude/mattermost-community-enterprise.git
|
||||
cd mattermost-community-enterprise
|
||||
```
|
||||
|
||||
### 4. 빌드
|
||||
|
||||
```bash
|
||||
# vendor 디렉토리 사용 (오프라인/에어갭 환경)
|
||||
go build -v -mod=vendor -o mattermost ./cmd/mattermost
|
||||
|
||||
# 또는 온라인 환경에서 최신 의존성 사용
|
||||
go mod download
|
||||
go build -v -o mattermost ./cmd/mattermost
|
||||
```
|
||||
|
||||
### 5. 디렉토리 구조 준비
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/mattermost/{bin,config,data,logs,plugins,client/plugins}
|
||||
|
||||
# 바이너리 복사
|
||||
cp mattermost /opt/mattermost/bin/
|
||||
|
||||
# 설정 및 리소스 복사
|
||||
cp -r config/* /opt/mattermost/config/
|
||||
cp -r i18n /opt/mattermost/
|
||||
cp -r fonts /opt/mattermost/
|
||||
cp -r templates /opt/mattermost/
|
||||
cp -r client/* /opt/mattermost/client/
|
||||
```
|
||||
|
||||
### 6. 데이터베이스 설정
|
||||
|
||||
**PostgreSQL 설치 및 설정:**
|
||||
|
||||
```bash
|
||||
# PostgreSQL 설치
|
||||
sudo dnf install -y postgresql-server postgresql
|
||||
sudo postgresql-setup --initdb
|
||||
sudo systemctl enable --now postgresql
|
||||
|
||||
# 데이터베이스 생성
|
||||
sudo -u postgres psql <<EOF
|
||||
CREATE DATABASE mattermost;
|
||||
CREATE USER mmuser WITH PASSWORD 'mmpassword';
|
||||
GRANT ALL PRIVILEGES ON DATABASE mattermost TO mmuser;
|
||||
ALTER DATABASE mattermost OWNER TO mmuser;
|
||||
\c mattermost
|
||||
GRANT ALL ON SCHEMA public TO mmuser;
|
||||
EOF
|
||||
```
|
||||
|
||||
### 7. 설정 파일 수정
|
||||
|
||||
`/opt/mattermost/config/config.json` 수정:
|
||||
|
||||
```json
|
||||
{
|
||||
"SqlSettings": {
|
||||
"DriverName": "postgres",
|
||||
"DataSource": "postgres://mmuser:mmpassword@localhost:5432/mattermost?sslmode=disable"
|
||||
},
|
||||
"ServiceSettings": {
|
||||
"SiteURL": "http://서버IP:8065",
|
||||
"ListenAddress": ":8065"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. 실행
|
||||
|
||||
```bash
|
||||
cd /opt/mattermost
|
||||
./bin/mattermost
|
||||
```
|
||||
|
||||
### 9. Systemd 서비스 등록 (선택)
|
||||
|
||||
`/etc/systemd/system/mattermost.service` 파일 생성:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Mattermost
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/opt/mattermost/bin/mattermost
|
||||
WorkingDirectory=/opt/mattermost
|
||||
User=mattermost
|
||||
Group=mattermost
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
LimitNOFILE=49152
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
서비스 활성화:
|
||||
|
||||
```bash
|
||||
# mattermost 사용자 생성
|
||||
sudo useradd -r -s /sbin/nologin mattermost
|
||||
sudo chown -R mattermost:mattermost /opt/mattermost
|
||||
|
||||
# 서비스 시작
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now mattermost
|
||||
sudo systemctl status mattermost
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HA 클러스터 구성
|
||||
|
||||
고가용성을 위해 여러 Mattermost 인스턴스를 클러스터로 구성할 수 있습니다.
|
||||
|
||||
### Redis 설정
|
||||
|
||||
클러스터 모드에서는 Redis가 필요합니다:
|
||||
|
||||
```bash
|
||||
docker run -d --name redis -p 6379:6379 redis:7
|
||||
```
|
||||
|
||||
### 환경 변수 설정
|
||||
|
||||
각 Mattermost 노드에서:
|
||||
|
||||
```bash
|
||||
export MM_CLUSTERSETTINGS_ENABLE=true
|
||||
export MM_CLUSTERSETTINGS_CLUSTERNAME=mattermost-cluster
|
||||
export MM_CLUSTERSETTINGS_REDISHOST=redis호스트:6379
|
||||
```
|
||||
|
||||
### HAProxy 로드밸런서
|
||||
|
||||
```
|
||||
frontend mattermost
|
||||
bind *:80
|
||||
default_backend mattermost_servers
|
||||
|
||||
backend mattermost_servers
|
||||
balance roundrobin
|
||||
cookie SERVERID insert indirect nocache
|
||||
server mm1 10.0.4.112:8065 check cookie mm1
|
||||
server mm2 10.0.4.49:8065 check cookie mm2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
### 빌드 오류: "cannot find module"
|
||||
|
||||
```bash
|
||||
# vendor 디렉토리 재생성
|
||||
go mod vendor
|
||||
```
|
||||
|
||||
### 실행 오류: "config.json not found"
|
||||
|
||||
```bash
|
||||
# 설정 파일 위치 지정
|
||||
./mattermost --config /opt/mattermost/config/config.json
|
||||
```
|
||||
|
||||
### 데이터베이스 연결 실패
|
||||
|
||||
1. PostgreSQL 서비스 상태 확인: `systemctl status postgresql`
|
||||
2. 연결 테스트: `psql -h localhost -U mmuser -d mattermost`
|
||||
3. pg_hba.conf에서 인증 방식 확인
|
||||
|
||||
### 포트 8065 접근 불가
|
||||
|
||||
```bash
|
||||
# 방화벽 포트 열기
|
||||
sudo firewall-cmd --permanent --add-port=8065/tcp
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 지원되는 Enterprise 기능
|
||||
|
||||
이 빌드에서 라이선스 없이 사용 가능한 기능:
|
||||
|
||||
- LDAP/AD 연동
|
||||
- SAML SSO
|
||||
- 고가용성 클러스터링
|
||||
- Prometheus 메트릭
|
||||
- 커스텀 권한 스키마
|
||||
- 데이터 보존 정책
|
||||
- 컴플라이언스 내보내기
|
||||
- 메시지 내보내기
|
||||
|
||||
자세한 내용은 `Extend-Function.md`와 `Unlock-License.md`를 참조하세요.
|
||||
|
||||
---
|
||||
|
||||
## 라이선스
|
||||
|
||||
이 프로젝트는 교육 및 개인 사용 목적으로 제공됩니다.
|
||||
상용 환경에서는 Mattermost 공식 라이선스 구매를 권장합니다.
|
||||
539
Unlock-License.md
Normal file
539
Unlock-License.md
Normal file
@ -0,0 +1,539 @@
|
||||
# Mattermost License Unlock Guide
|
||||
|
||||
이 문서는 Mattermost Team Edition에서 Enterprise 기능을 라이선스 없이 사용할 수 있도록 수정한 내용을 상세히 설명합니다.
|
||||
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
Mattermost Enterprise 기능은 두 가지 레벨에서 제어됩니다:
|
||||
|
||||
1. **인터페이스 구현체**: Enterprise 기능의 실제 코드 (LDAP, SAML, Cluster 등)
|
||||
2. **API 라이선스 체크**: REST API에서 라이선스 유무 확인
|
||||
|
||||
이 프로젝트는 두 가지를 모두 해결합니다:
|
||||
- Enterprise 구현체를 `enterprise-impl/` 디렉토리에 오픈소스로 제공
|
||||
- API의 라이선스 체크 코드를 제거
|
||||
|
||||
---
|
||||
|
||||
## 라이선스 체크 제거 상세
|
||||
|
||||
### 1. LDAP API (channels/api4/ldap.go)
|
||||
|
||||
#### 1.1 syncLdap() - LDAP 동기화
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func syncLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError("Api4.syncLdap", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ... 나머지 코드
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func syncLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateLdapSyncJob) {
|
||||
c.SetPermissionError(model.PermissionCreateLdapSyncJob)
|
||||
return
|
||||
}
|
||||
// ... 나머지 코드
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 testLdap() - LDAP 연결 테스트
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func testLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError("Api4.testLdap", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func testLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionTestLdap) {
|
||||
c.SetPermissionError(model.PermissionTestLdap)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 getLdapGroups() - LDAP 그룹 조회
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func getLdapGroups(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.getLdapGroups", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func getLdapGroups(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadUserManagementGroups) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleReadUserManagementGroups)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.4 linkLdapGroup() - LDAP 그룹 연결
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.linkLdapGroup", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementGroups) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementGroups)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.5 unlinkLdapGroup() - LDAP 그룹 연결 해제
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func unlinkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.unlinkLdapGroup", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func unlinkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementGroups) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementGroups)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.6 migrateIdLdap() - LDAP ID 마이그레이션
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func migrateIdLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError("Api4.migrateIdLdap", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func migrateIdLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
|
||||
c.SetPermissionError(model.PermissionManageSystem)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.7 createLdapPublicCertificate() - LDAP 인증서 생성
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func createLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError("Api4.createLdapPublicCertificate", "api.ldap.license.error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func createLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteAuthenticationLdap) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteAuthenticationLdap)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Scheme API (channels/api4/scheme.go)
|
||||
|
||||
커스텀 권한 스키마 기능의 라이선스 체크를 제거했습니다.
|
||||
|
||||
#### 2.1 createScheme() - 스키마 생성
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func createScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.CustomPermissionsSchemes {
|
||||
c.Err = model.NewAppError("Api4.CreateScheme", "api.scheme.create_scheme.license.error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func createScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementPermissions) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementPermissions)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 patchScheme() - 스키마 수정
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.CustomPermissionsSchemes {
|
||||
c.Err = model.NewAppError("Api4.PatchScheme", "api.scheme.patch_scheme.license.error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
// ...
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementPermissions) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementPermissions)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3 deleteScheme() - 스키마 삭제
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func deleteScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.CustomPermissionsSchemes {
|
||||
c.Err = model.NewAppError("Api4.DeleteScheme", "api.scheme.delete_scheme.license.error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func deleteScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementPermissions) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementPermissions)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Group API (channels/api4/group.go)
|
||||
|
||||
팀/채널 그룹 기능의 라이선스 체크를 제거했습니다.
|
||||
|
||||
#### 3.1 getGroupsByTeamCommon() - 팀별 그룹 조회
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func getGroupsByTeamCommon(c *Context, r *http.Request) ([]byte, *model.AppError) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups {
|
||||
return nil, model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func getGroupsByTeamCommon(c *Context, r *http.Request) ([]byte, *model.AppError) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionViewTeam) {
|
||||
return nil, c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionViewTeam})
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 getGroupsByChannelCommon() - 채널별 그룹 조회
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func getGroupsByChannelCommon(c *Context, r *http.Request) ([]byte, *model.AppError) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups {
|
||||
return nil, model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func getGroupsByChannelCommon(c *Context, r *http.Request) ([]byte, *model.AppError) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
// Permission check follows...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. User API (channels/api4/user.go)
|
||||
|
||||
사용자 인증 마이그레이션의 라이선스 체크를 제거했습니다.
|
||||
|
||||
#### 4.1 migrateAuthToLdap() - LDAP 인증 마이그레이션
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func migrateAuthToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError("Api4.migrateAuthToLdap", "api.user.migrate_auth.license.app_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func migrateAuthToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
// Email auth in Mattermost system is represented by ""
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2 migrateAuthToSaml() - SAML 인증 마이그레이션
|
||||
|
||||
**원본 코드:**
|
||||
```go
|
||||
func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.SAML {
|
||||
c.Err = model.NewAppError("Api4.migrateAuthToSaml", "api.user.migrate_auth.license.app_error", nil, "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후:**
|
||||
```go
|
||||
func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
// ...
|
||||
// Community Enterprise: License check removed for open source usage
|
||||
|
||||
if from == "email" {
|
||||
from = ""
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Metrics (channels/app/platform/metrics.go)
|
||||
|
||||
Prometheus 메트릭 엔드포인트가 404를 반환하던 문제를 수정했습니다.
|
||||
|
||||
**추가된 인터페이스:**
|
||||
```go
|
||||
// MetricsHandlerProvider is an interface for metrics implementations that can provide an HTTP handler
|
||||
type MetricsHandlerProvider interface {
|
||||
Handler() http.Handler
|
||||
}
|
||||
```
|
||||
|
||||
**initMetricsRouter()에 추가된 코드:**
|
||||
```go
|
||||
// Register /metrics handler if metrics implementation provides a handler
|
||||
if pm.metricsImpl != nil {
|
||||
if handlerProvider, ok := pm.metricsImpl.(MetricsHandlerProvider); ok {
|
||||
pm.router.Handle("/metrics", handlerProvider.Handler())
|
||||
pm.logger.Info("Metrics endpoint registered at /metrics")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 라이선스 체크 패턴
|
||||
|
||||
Mattermost 코드에서 라이선스 체크는 일반적으로 다음 패턴을 따릅니다:
|
||||
|
||||
```go
|
||||
// 패턴 1: 단순 nil 체크
|
||||
if c.App.Channels().License() == nil {
|
||||
c.Err = model.NewAppError(...)
|
||||
return
|
||||
}
|
||||
|
||||
// 패턴 2: nil 체크 + 기능 플래그
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAP {
|
||||
c.Err = model.NewAppError(...)
|
||||
return
|
||||
}
|
||||
|
||||
// 패턴 3: 기능 플래그만 체크
|
||||
if !*c.App.Channels().License().Features.CustomPermissionsSchemes {
|
||||
c.Err = model.NewAppError(...)
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
### 제거 방법
|
||||
|
||||
1. 라이선스 체크 조건문 전체를 삭제
|
||||
2. 주석으로 표시: `// Community Enterprise: License check removed for open source usage`
|
||||
3. 권한 체크만 남김 (보안 유지)
|
||||
|
||||
---
|
||||
|
||||
## 추가 라이선스 체크 위치
|
||||
|
||||
다른 Enterprise 기능에도 라이선스 체크가 있을 수 있습니다. 찾는 방법:
|
||||
|
||||
```bash
|
||||
# 모든 라이선스 체크 찾기
|
||||
grep -r "License()" channels/api4/ | grep -v "_test.go"
|
||||
|
||||
# 특정 기능의 라이선스 체크
|
||||
grep -r "Features.SAML" channels/api4/
|
||||
grep -r "Features.Cluster" channels/api4/
|
||||
grep -r "Features.Compliance" channels/api4/
|
||||
grep -r "Features.DataRetention" channels/api4/
|
||||
grep -r "Features.MessageExport" channels/api4/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UI 라이선스 체크
|
||||
|
||||
웹 클라이언트(React)에도 라이선스 체크가 있습니다:
|
||||
|
||||
```
|
||||
client/
|
||||
├── *.js # Minified JavaScript
|
||||
└── *.js.map # Source maps
|
||||
```
|
||||
|
||||
JavaScript 파일은 minified 상태라 직접 수정이 어렵습니다.
|
||||
|
||||
### 해결 방법 옵션
|
||||
|
||||
1. **webapp 소스 빌드**: mattermost/mattermost-webapp 저장소에서 소스를 수정하고 다시 빌드
|
||||
2. **API만 사용**: API는 라이선스 체크가 제거되었으므로 CLI나 API 호출로 기능 사용
|
||||
3. **커스텀 플러그인**: 웹 UI를 우회하는 플러그인 개발
|
||||
|
||||
---
|
||||
|
||||
## 면책 조항
|
||||
|
||||
이 수정은 교육 및 개인 학습 목적으로 제공됩니다. 상용 환경에서는 Mattermost 공식 라이선스를 구매하시기 바랍니다.
|
||||
|
||||
Enterprise 기능의 전체 지원과 업데이트를 받으려면 공식 라이선스가 필요합니다.
|
||||
|
||||
---
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- [Mattermost 공식 문서](https://docs.mattermost.com/)
|
||||
- [Mattermost GitHub](https://github.com/mattermost/mattermost)
|
||||
- [einterfaces 정의](https://github.com/mattermost/mattermost/tree/master/server/channels/einterfaces)
|
||||
Loading…
Reference in New Issue
Block a user