| 
                        123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 | 
                        - # -*- coding:utf-8 -*-
 - from datetime import datetime
 - 
 - from flask_login import login_required, current_user
 - from flask_restful import Resource, reqparse, fields, marshal_with, abort, inputs
 - from sqlalchemy import and_
 - 
 - from controllers.console import api
 - from extensions.ext_database import db
 - from models.model import Tenant, App, InstalledApp, RecommendedApp
 - from services.account_service import TenantService
 - 
 - app_fields = {
 -     'id': fields.String,
 -     'name': fields.String,
 -     'mode': fields.String,
 -     'icon': fields.String,
 -     'icon_background': fields.String
 - }
 - 
 - installed_app_fields = {
 -     'id': fields.String,
 -     'app': fields.Nested(app_fields, attribute='app'),
 -     'app_owner_tenant_id': fields.String,
 -     'is_pinned': fields.Boolean,
 -     'last_used_at': fields.DateTime,
 -     'editable': fields.Boolean
 - }
 - 
 - installed_app_list_fields = {
 -     'installed_apps': fields.List(fields.Nested(installed_app_fields))
 - }
 - 
 - recommended_app_fields = {
 -     'app': fields.Nested(app_fields, attribute='app'),
 -     'app_id': fields.String,
 -     'description': fields.String(attribute='description'),
 -     'copyright': fields.String,
 -     'privacy_policy': fields.String,
 -     'category': fields.String,
 -     'position': fields.Integer,
 -     'is_listed': fields.Boolean,
 -     'install_count': fields.Integer,
 -     'installed': fields.Boolean,
 -     'editable': fields.Boolean
 - }
 - 
 - recommended_app_list_fields = {
 -     'recommended_apps': fields.List(fields.Nested(recommended_app_fields)),
 -     'categories': fields.List(fields.String)
 - }
 - 
 - 
 - class InstalledAppsListResource(Resource):
 -     @login_required
 -     @marshal_with(installed_app_list_fields)
 -     def get(self):
 -         current_tenant_id = Tenant.query.first().id
 -         installed_apps = db.session.query(InstalledApp).filter(
 -             InstalledApp.tenant_id == current_tenant_id
 -         ).all()
 - 
 -         current_user.role = TenantService.get_user_role(current_user, current_user.current_tenant)
 -         installed_apps = [
 -             {
 -                 **installed_app,
 -                 "editable": current_user.role in ["owner", "admin"],
 -             }
 -             for installed_app in installed_apps
 -         ]
 -         installed_apps.sort(key=lambda app: (-app.is_pinned, app.last_used_at))
 - 
 -         return {'installed_apps': installed_apps}
 - 
 -     @login_required
 -     def post(self):
 -         parser = reqparse.RequestParser()
 -         parser.add_argument('app_id', type=str, required=True, help='Invalid app_id')
 -         args = parser.parse_args()
 - 
 -         current_tenant_id = Tenant.query.first().id
 -         app = App.query.get(args['app_id'])
 -         if app is None:
 -             abort(404, message='App not found')
 -         recommended_app = RecommendedApp.query.filter(RecommendedApp.app_id == args['app_id']).first()
 -         if recommended_app is None:
 -             abort(404, message='App not found')
 -         if not app.is_public:
 -             abort(403, message="You can't install a non-public app")
 - 
 -         installed_app = InstalledApp.query.filter(and_(
 -             InstalledApp.app_id == args['app_id'],
 -             InstalledApp.tenant_id == current_tenant_id
 -         )).first()
 - 
 -         if installed_app is None:
 -             # todo: position
 -             recommended_app.install_count += 1
 - 
 -             new_installed_app = InstalledApp(
 -                 app_id=args['app_id'],
 -                 tenant_id=current_tenant_id,
 -                 is_pinned=False,
 -                 last_used_at=datetime.utcnow()
 -             )
 -             db.session.add(new_installed_app)
 -             db.session.commit()
 - 
 -         return {'message': 'App installed successfully'}
 - 
 - 
 - class InstalledAppResource(Resource):
 - 
 -     @login_required
 -     def delete(self, installed_app_id):
 - 
 -         installed_app = InstalledApp.query.filter(and_(
 -             InstalledApp.id == str(installed_app_id),
 -             InstalledApp.tenant_id == current_user.current_tenant_id
 -         )).first()
 - 
 -         if installed_app is None:
 -             abort(404, message='App not found')
 - 
 -         if installed_app.app_owner_tenant_id == current_user.current_tenant_id:
 -             abort(400, message="You can't uninstall an app owned by the current tenant")
 - 
 -         db.session.delete(installed_app)
 -         db.session.commit()
 - 
 -         return {'result': 'success', 'message': 'App uninstalled successfully'}
 - 
 -     @login_required
 -     def patch(self, installed_app_id):
 -         parser = reqparse.RequestParser()
 -         parser.add_argument('is_pinned', type=inputs.boolean)
 -         args = parser.parse_args()
 - 
 -         current_tenant_id = Tenant.query.first().id
 -         installed_app = InstalledApp.query.filter(and_(
 -             InstalledApp.id == str(installed_app_id),
 -             InstalledApp.tenant_id == current_tenant_id
 -         )).first()
 - 
 -         if installed_app is None:
 -             abort(404, message='Installed app not found')
 - 
 -         commit_args = False
 -         if 'is_pinned' in args:
 -             installed_app.is_pinned = args['is_pinned']
 -             commit_args = True
 - 
 -         if commit_args:
 -             db.session.commit()
 - 
 -         return {'result': 'success', 'message': 'App info updated successfully'}
 - 
 - 
 - class RecommendedAppsResource(Resource):
 -     @login_required
 -     @marshal_with(recommended_app_list_fields)
 -     def get(self):
 -         recommended_apps = db.session.query(RecommendedApp).filter(
 -             RecommendedApp.is_listed == True
 -         ).all()
 - 
 -         categories = set()
 -         current_user.role = TenantService.get_user_role(current_user, current_user.current_tenant)
 -         recommended_apps_result = []
 -         for recommended_app in recommended_apps:
 -             installed = db.session.query(InstalledApp).filter(
 -                 and_(
 -                     InstalledApp.app_id == recommended_app.app_id,
 -                     InstalledApp.tenant_id == current_user.current_tenant_id
 -                 )
 -             ).first() is not None
 - 
 -             language_prefix = current_user.interface_language.split('-')[0]
 -             desc = None
 -             if recommended_app.description:
 -                 if language_prefix in recommended_app.description:
 -                     desc = recommended_app.description[language_prefix]
 -                 elif 'en' in recommended_app.description:
 -                     desc = recommended_app.description['en']
 - 
 -             recommended_app_result = {
 -                 'id': recommended_app.id,
 -                 'app': recommended_app.app,
 -                 'app_id': recommended_app.app_id,
 -                 'description': desc,
 -                 'copyright': recommended_app.copyright,
 -                 'privacy_policy': recommended_app.privacy_policy,
 -                 'category': recommended_app.category,
 -                 'position': recommended_app.position,
 -                 'is_listed': recommended_app.is_listed,
 -                 'install_count': recommended_app.install_count,
 -                 'installed': installed,
 -                 'editable': current_user.role in ['owner', 'admin'],
 -             }
 -             recommended_apps_result.append(recommended_app_result)
 - 
 -             categories.add(recommended_app.category)  # add category to categories
 - 
 -         return {'recommended_apps': recommended_apps_result, 'categories': list(categories)}
 - 
 - 
 - api.add_resource(InstalledAppsListResource, '/installed-apps')
 - api.add_resource(InstalledAppResource, '/installed-apps/<uuid:installed_app_id>')
 - api.add_resource(RecommendedAppsResource, '/explore/apps')
 
 
  |