def change_bucket_expired_date(bucket, expired_date=None, days=None, order_id=None, **kwargs): if expired_date is None and days is None: # by default, 30 days free_days = to_int(get_env("free_days"), default_if_fail=30) or 30 expired_date = datetime.datetime.utcnow() + datetime.timedelta( days=free_days) elif isinstance(days, (int, float)): # 指定扩展的天数 now = datetime.datetime.utcnow() current_expired_date = get_bucket_expired_date(bucket) or now if current_expired_date < now: current_expired_date = now expired_date = current_expired_date + datetime.timedelta(days=days) if not isinstance(expired_date, datetime.datetime): try: expired_date = utc_date_parse(expired_date) except: return set_bucket_service_info(bucket, expired_date=expired_date, order_id=order_id, **kwargs)
def get_domains_from_env(key): raw_domains = get_env(key) or '' domain_list = re.split('[,\n]', raw_domains) domains_got = [] for domain in domain_list: domain = domain.strip().lower() if domain not in domains_got and domain: domains_got.append(domain) return domains_got
def create_new_bucket_for_user_step_1(): register_note = get_env("register_note") or "" info = "" invitation_code = request.values.get("invitation_code") if invitation_code: if not check_invitation_by_web_request(): info = "invalid invitation code or used" else: # 跳转到创建 bucket 的逻辑 return p_redirect("__create_bucket?invitation_code=%s" % invitation_code) return render_api_template_as_response("page_user_register.jade", info=info, register_note=register_note)
def login(): set_not_cache_current_request() bucket = get_logined_bucket(check=True) if bucket: email = get_bucket_owner_email(bucket) else: email = "" show_donation = auto_type(get_env("show_donation")) response = render_api_template_as_response( "page_user_admin.jade", email=email, show_donation=show_donation, is_wechat_server_valid=is_wechat_server_valid) return response
def allowed_to_display_some_bucket_info(bucket=None): if bucket: set_pending_bucket_bucket_in_request(bucket) # 校验用的 logined_bucket = get_logined_bucket_by_token() if not logined_bucket: raw_token = request.values.get("api_token") or request.values.get( "token") or "" if raw_token: endpoint_password = get_env("endpoint_password") if endpoint_password and endpoint_password == raw_token: return True if not logined_bucket: logined_bucket = get_logined_bucket() # try again, by cookie if logined_bucket and logined_bucket == bucket: return True return False
def get_remote_nodes_to_sync_from(): # 从本地配置中,引入要同步的节点 list,每一行一条记录; 简单有效的是,每行一个 ip # 如果 node 本身没有 :<port> 的声明, 默认会认为是 :7788 端口 nodes = [] raw_content = get_env("server_sync_nodes") or "" lines = raw_content.split(',') for line in lines: line = line.strip() if line.startswith('#'): continue if not line: continue if ':' not in line: line = '%s:7788' % line nodes.append(line) return nodes
def sync_from_remote_node(remote_node): # 从 remote node 上完全同步所有 buckets 的时候, 每次任务实际上是每次 1000 个 buckets # 在下次 cronjob 触发的时候,会在上次 cursor 保存的状态后,进行后面 1000 个同步,如此周而复始 buckets, cursor = get_buckets_to_sync_from_remote_node(remote_node) if not buckets: return server_sync_token = get_env("server_sync_token") if not server_sync_token: return callback_func = partial(set_buckets_cursor_for_remote_node, remote_node, cursor) job_func = partial(sync_bucket_from_remote_node, remote_node=remote_node, server_sync_token=server_sync_token) do_by_gevent_pool(pool_size=100, job_func=job_func, loop_items=buckets, timeout=30 * 60, callback_func=callback_func)
def create_new_bucket_for_user_step_2(): # 这个也负责初次的安装,还没有 bucket 的时候 register_note = get_env("register_note") or "" private_key = request.values.get( "private_key") or get_private_key_on_server_side() info = "" invitation_code = request.values.get( "invitation_code") or request.values.get("code") if request.method == "POST": info = create_bucket_by_web_request(invitation_code) if not info: # 创建成功了 return p_redirect("/admin") else: # GET if invitation_code != "admin" and not check_invitation_by_web_request( ): info = "invalid invitation code" return render_api_template_as_response("page_user_create_bucket.jade", private_key=private_key, info=info, register_note=register_note)
def show_bucket_records_for_web_request(bucket=None, default_records_per_page=100, includes_zero_ids=True, cursor=None, per_page=None): # return response or abort error # 注意: 如果传入一个有效的 bucket,那么是不会进行校验的 bucket = bucket or get_logined_bucket_by_token() # by api token if not bucket: # 服务器端同步相关的逻辑在这里判断 server_sync_token = request.values.get("server_sync_token", "") if server_sync_token and server_sync_token == get_env("server_sync_token"): bucket = get_pending_bucket_bucket_in_request() if not bucket: abort(404, "no bucket matched") set_bucket_in_request_context(bucket) pre_record_id = cursor or request.values.get('cursor') if not includes_zero_ids and not pre_record_id: # 不包括 zero ids 相当于 pre_record_id = zero_id_for_finder per_page = per_page or to_per_page(default_records_per_page, request.values.get('per_page'), max_per_page=1000) records = get_records_for_bucket(bucket, start_record_id=pre_record_id, limit=per_page) return jsonify(records)
def init_server_status_bucket(): if 'utc_offset' not in os.environ: # 统计系统信息时候,可读性使用的 utc_offset utc_offset = get_env('utc_offset') if utc_offset is None: utc_offset = 8 try: utc_offset = str(utc_offset) except: utc_offset = '8' os.environ['utc_offset'] = utc_offset configs = get_server_status_bucket_configs() bucket = configs['bucket'] public_key = configs['public_key'] if has_bucket(bucket): return create_bucket_by_public_key(public_key) set_bucket_configs(bucket, config_type='pages', configs=bucket_web_template)
def extend_bucket_yearly(): # 考虑到 alipay 的回调,这里不限制 bucket 是否处于登录的状态 bucket = get_logined_bucket(check=True) service_info = get_bucket_service_info(bucket) order_ids = service_info.get("order_id_list") or [] if not isinstance(order_ids, (list, tuple)): order_ids = [] price = BUCKET_PRICE price2 = BUCKET_PRICE2 price_note = get_env("bucket_price_note") or "" if request.method == "GET" and not request.values.get( "trade_no") and request.values.get("action") != "do": # 不需要处理,直接呈现页面 return render_api_template_as_response("page_user_extend_bucket.jade", order_ids=order_ids, service_info=service_info, price=price, price2=price2, price_note=price_note) try_price2 = request.values.get("try_price2") in ["yes", "true"] to_handle = extend_bucket_expired_date_yearly_by_alipay( bucket, try_price2=try_price2) if to_handle: # 更新一次 service_info = get_bucket_service_info(bucket) order_ids = service_info.get("order_id_list") or [] if not isinstance(order_ids, (list, tuple)): order_ids = [] return render_api_template_as_response("page_user_extend_bucket.jade", order_ids=order_ids, service_info=service_info, price=price, price2=price2, price_note=price_note)
#coding: utf8 import requests from farbox_bucket.utils.ssdb_utils import auto_cache_by_ssdb from farbox_bucket.utils.env import get_env WECHAT_APP_ID = get_env("wechat_app_id") WECHAT_APP_SECRET = get_env("wechat_app_secret") # 一个微信的open id 看起来可能是这样的: oZ454jpVhF15nHxs3ig-uCq_gqss API_PREFIX = 'https://api.weixin.qq.com/cgi-bin/' # 每天最多 2000 次 def _get_access_token(): if not WECHAT_APP_ID or not WECHAT_APP_SECRET: return "" url = API_PREFIX + 'token' params = { 'grant_type': 'client_credential', 'appid': WECHAT_APP_ID, 'secret': WECHAT_APP_SECRET } response = requests.get(url, params=params, verify=False) try: token = response.json().get('access_token') except: try: print(response.json().get("errmsg")) except: pass
# coding: utf8 import re from flask import request, Response from farbox_bucket.utils import to_float from farbox_bucket.utils.functional import cached_property from farbox_bucket.utils.env import get_env from .alipay_api import AlipayAPI ALIPAY_PID = get_env('ALIPAY_PID') ALIPAY_APP_ID = get_env('ALIPAY_APP_ID') ALIPAY_PRIVATE_KEY = get_env('ALIPAY_PRIVATE_KEY') ALIPAY_PUBLIC_KEY = get_env('ALIPAY_PUBLIC_KEY') class AliPay(object): def __init__(self, private_key=None, public_key=None, pid=None, app_id=None): self.alipay_public_key = public_key or ALIPAY_PUBLIC_KEY self.alipay_private_key = private_key or ALIPAY_PRIVATE_KEY self.alipay_pid = pid or ALIPAY_PID self.alipay_app_id = app_id or ALIPAY_APP_ID @cached_property def alipay_api(self): if self.alipay_pid and self.alipay_private_key: # and self.alipay_public_key alipay_api = AlipayAPI(private_key=self.alipay_private_key, public_key=self.alipay_public_key, pid=self.alipay_pid,
#coding: utf8 from __future__ import absolute_import from farbox_bucket.utils.env import get_env from farbox_bucket.server.backend.service import keep_watch_nginx, restart_backend_per_day, keep_watch_memcache, run_logrotate should_sync_buckets = get_env("should_sync_buckets_in_backend") if should_sync_buckets == "no": should_sync_buckets = False backend_jobs = [ keep_watch_nginx, keep_watch_memcache, restart_backend_per_day, run_logrotate, ] if should_sync_buckets: # 减少 backend 的内存占用,如果只是守护性质的话 from farbox_bucket.server.backend.sync.buckets import sync_buckets_from_remote_marked, sync_buckets_from_remote_nodes backend_jobs.append(sync_buckets_from_remote_marked) backend_jobs.append(sync_buckets_from_remote_nodes)
# coding: utf8 import xmltodict from flask import request from farbox_bucket.settings import DEBUG from farbox_bucket.utils import smart_unicode from farbox_bucket.utils.env import get_env from farbox_bucket.utils.memcache_block import is_blocked from farbox_bucket.clouds.wechat.utils.check import check_is_from_wechat from farbox_bucket.clouds.wechat.utils.message import send_wechat_message from .wechat_text_image_sync_worker import wechat_text_image_handler from .bind_wechat import unbind_wechat_account, get_wechat_account_bind_status_reply, bind_bucket_by_wechat, \ get_bucket_by_wechat_user_id WECHAT_TOKEN = (get_env("wechat_token") or "").strip() is_wechat_server_valid = True if WECHAT_TOKEN else False def compile_for_wechat(raw_data): if isinstance(raw_data, dict): xml_data = raw_data else: xml_data = xmltodict.parse(raw_data)["xml"] wechat_user_id = xml_data.get("FromUserName") msg_type = xml_data.get("MsgType") event_name = (xml_data.get("Event") or "").lower() event_key = (xml_data.get("EventKey") or "").lower() #with open("/tmp/test.json", "w") as f:
from farbox_bucket.server.utils.request_context_vars import is_resource_in_loads_in_page_already,\ get_i18n_data_from_request, set_i18n_data_to_request from farbox_bucket.server.utils.request_path import auto_bucket_url_path, get_request_path_for_bucket from farbox_bucket.server.static.static_render import web_static_resources_map, static_folder_path from farbox_bucket.server.template_system.api_template_render import render_api_template from farbox_bucket.server.template_system.namespace.utils.form_utils import create_simple_form, create_grid_form, \ create_form_dom_by_field as _create_form_dom_by_field, create_form_dom as _create_form_dom, \ get_data_obj_from_POST as form_get_data_obj_from_POST from farbox_bucket.server.template_system.namespace.utils.nav_utils import pre_nav_data from farbox_bucket.server.helpers.smart_scss import get_smart_scss_url from farbox_bucket.server.realtime.utils import get_bucket_ws_url static_files_url = (get_env("static_files_url") or "").strip().strip("/") qcloud_cdn_token = (get_env("qcloud_cdn_token") or "").strip() def get_a_random_dom_id(): dom_id = 'd%s' % uuid.uuid1().hex return dom_id lazy_load_map = { 'font': '/fb_static/lib/fontawesome/css/font-awesome.min.css', 'jquery': '/fb_static/lib/jquery.js', 'pure': ['/fb_static/lib/pure.css', '/fb_static/lib/pure_patch.css'], 'form':
# coding: utf8 from farbox_bucket.utils.env import get_env from farbox_bucket.clouds.qcloud import upload_file_obj_to_qcloud, delete_file_on_qcloud,\ has_file_on_qcloud, get_file_content_from_qcloud raw_qcloud_config = get_env('qcloud') QCLOUD_REGION = get_env("qcloud_region") or 'ap-shanghai' QCLOUD_BUCKET = get_env("qcloud_bucket") QCLOUD_SECRET_ID = get_env("qcloud_secret_id") QCLOUD_SECRET_KEY = get_env("qcloud_secret_key") if QCLOUD_BUCKET and QCLOUD_SECRET_ID and QCLOUD_SECRET_KEY: qcloud_is_valid = True else: qcloud_is_valid = False QCLOUD_URL = (get_env("qcloud_url") or "").rstrip("/") QCLOUD_CDN_TOKEN = (get_env("qcloud_cdn_token") or "").strip() def upload_file_to_qcloud_for_bucket(bucket, relative_path, file_obj, content_type="", **headers): if not qcloud_is_valid: return False # ignore relative_path = relative_path.strip('/') url_path = '%s/%s' % (bucket, relative_path) uploaded = upload_file_obj_to_qcloud(file_obj=file_obj, url_path=url_path,
#coding: utf8 from __future__ import absolute_import import re, os, sys, uuid from raven import Client from farbox_bucket.utils import to_float, to_int from farbox_bucket.utils.path import read_file, write_file from farbox_bucket.utils.env import get_env from farbox_bucket.utils.ssdb_client import SSDB_Client from farbox_bucket import version from farbox_bucket.utils.encrypt.simple import ServerSerializer from farbox_bucket.server.dangerous.start_elasticsearch_server import auto_reset_elasticsearch_memory_config_when_app_started ssdb_ip = get_env('SSDB_IP') or '127.0.0.1' ssdb_port = get_env('SSDB_PORT') or 8888 try: ssdb_port = int(ssdb_port) except: ssdb_port = 8888 db_client = SSDB_Client(ssdb_ip, ssdb_port) STATIC_FILE_VERSION = version # 静态资源通过 h.load 载入的时候,增加 version 的逻辑 # Markdown 解析的时候会有扩容的情况,估计 100k 的(多行)文档会膨胀到 500k MAX_RECORD_SIZE = 500 * 1024 # 500Kb # 这个只是对 verify 时候起作用的,如果是 system 直接写入的,不在受限范围 MAX_RECORD_SIZE_FOR_CONFIG = 800 * 1024 ## 800Kb MAX_FILE_SIZE = to_int( get_env("MAX_FILE_SIZE")) or 50 * 1024 * 1024 # 最大文件 50 Mb
# coding: utf8 from flask import abort from farbox_bucket.utils.env import get_env from farbox_bucket.server.web_app import app from farbox_bucket.bucket.token.utils import get_logined_bucket from farbox_bucket.clouds.wechat.bind_wechat import get_wechat_bind_code_for_bucket, get_wechat_user_docs_by_bucket from farbox_bucket.server.template_system.api_template_render import render_api_template_as_response from .wechat_handler import wechat_web_handler, WECHAT_TOKEN # 公众号后台获得公众号二维码,解析后是一个 URL 的字符串 wechat_account_url = get_env("wechat_account_url") or "" wechat_account_url2 = get_env("wechat_account_url2") or "" @app.route("/__wechat_api", methods=["POST", "GET"]) def wechat_api_view(): return wechat_web_handler() @app.route("/__wechat_bind", methods=["POST", "GET"]) def wechat_bind_view(): if not WECHAT_TOKEN or not wechat_account_url: abort(404, "Wechat is not valid in current service") else: logined_bucket = get_logined_bucket(check=True) if not logined_bucket: return abort(404, "not login") bind_code = get_wechat_bind_code_for_bucket(logined_bucket) wechat_user_docs = get_wechat_user_docs_by_bucket(logined_bucket, with_name=True) response = render_api_template_as_response(